#include <iostream.h>
class A{
private:
int x,y ;
public:
A(int a=0,int b=0){y=b;x=a;}
void init(int a,int b){x=a;y=b;}
void show(){cout<<x<<" "<<y<<endl;}
};
void main()
{
A l[5]={(1,1),(2,2),(3,3),(4,4),(5,5)};
A *p;
p=l;
l[3].init(8,3);
p->init(3,4);
for(int i=0;i<5;i++)
(*(p+i)).show();
}
when i execute this code,I[0] was shown (1.0),but I assign it (1,1),i[0] was not assigned.so was i[1],i[2]...
What can i do to assign i[5]?thanks very much.
kuphryn
October 27th, 2002, 11:07 PM
Index count begins with 0. That is a fundamental concept of computer architecture.
If you want to start with array[1], array[2], etc. then you should ignore array[0]. In your example, create six arrays.
Kuphryn
xixi
October 27th, 2002, 11:28 PM
In my program ,i assign array like this:
A l[5]={(1,1),(2,2),(3,3),(4,4),(5,5)};
but it execute like this :
1 0
2 0
3 0
4 0
5 0
it like:
y of class A is not assigned.but x of class A is assigned.
why?thank you .What can i do to assign y of class A?
kuphryn
October 27th, 2002, 11:47 PM
One solution is a loop.
for (unsigned int i = 0; i < 5; ++i)
I[i].Create(i + i, i + i);
Kuphryn
Graham
October 28th, 2002, 03:35 AM
Try this:
A l[5]={A(1,1), A(2,2), A(3,3), A(4,4), A(5,5)};
dumah
October 28th, 2002, 04:53 AM
Although it ugly, there is a way to use Kuphryn's loop and Graham's constructor method in one.
This code relies on operator new[] that's provided in the <new> header and then using placement new to initialise each object's construction in a loop. Unfortunately it looks nasty, it's not easy to see what's going on, and you nust control the destruction and memory freeing yourself
#include <new>
#include <iostream>
class A{
int x,y ;
public:
A(int a=0,int b=0){y=b;x=a;}
void init(int a,int b){x=a;y=b;}
void show(){std::cout << x << " " << y << std::endl;}
};
int main(){
const int nArrSz = 5;
A *l = static_cast<A*>(operator new[] (nArrSz * sizeof(A)));//Allocate raw memory
if(!l){
std::cout << "Error" << std::endl;
return 1;
}
for(int i = 0;i < nArrSz;i++)
new (l+i) A(i+1,i+1);//Call constructor for each object in array
A *p;
p=l;
l[3].init(8,3);
p->init(3,4);
for(int i=0;i<5;i++)
(*(p+i)).show();
for(int i = 0;i < nArrSz;i++)
l[i].~A();//Call destuctor for each object in array
operator delete[] (l);//free memory
}
Enjoy!
AnthonyMai
October 28th, 2002, 08:19 AM
[Y: Solution exploiting struct-like behaviour]
What the OP needs to do is:
1.Change the "private" to public. If you need to initialize the class member from an array, it needs to be accessible so you can't hide with "private".
2.Remove any constructor you declared. The compiler will decide how to initialize the object, not you.
3.Change the round bracket in your parameter list to curly bracket.
This is how the working code looks like:
//...
class A
{
public:
int x;
int y;
public:
void init(int a,int b){x=a;y=b;}
void show() {printf("%d %d\r\n", x, y);}
};
int main(int argc, char* argv[])
{
A l[5] = {{1,1},{2,2},{3,3},{4,4},{5,5}};
//...
}
[Yves : cleaned up the post a bit]
PaulWendt
October 28th, 2002, 09:43 AM
Originally posted by AnthonyMai
I just don't understand why the OP posted something so simple and straightforward and no one can give a correct and straight answer?
I didn't find a problem with some of the answers here; maybe
they didn't want to totally alter his class design. What was wrong
with Graham's response?
What the OP needs to do is:
1.Change the "private" to public. If you need to initialize the class member from an array, it needs to be accessible so you can't hide with "private".
... and what if the OP wants to use the information-hiding ideas
inherent in C++? It can be difficult to make an abstract data
type of others can get access to your private members.
2.Remove any constructor you declared. The compiler will decide how to initialize the object, not you.
... and what if the OP wants to provide some other form of
initialization in this class? I don't think he should be forced to
use inheritance to create such a simplistic class.
Just as an aside, just because you can change a bunch of things
in order to "implement a solution", it doesn't mean it's an ideal
solution. Frankly, I wouldn't want to compromise my class design
so radically like you suggest; I'd rather use any number of
alternative methods.
--Paul
dumah
October 28th, 2002, 09:50 AM
Originally posted by AnthonyMai
I just don't understand why the OP posted something so simple and straightforward and no one can give a correct and straight answer?
As I see it, there is no correct & straight answer. Your idea may indeed be closest to how the OP was attempting this, but it involves him changing how the class operates and the privilege levels of the data members, so therefore its not the definitive answer.
Only the OP can decide which of the methods presented fits closest to what he/ she wants to do
dumah
October 28th, 2002, 09:51 AM
Apologies to previous poster. Didnt see your response when I began mine.
Graham
October 28th, 2002, 10:55 AM
Originally posted by AnthonyMai
I just don't understand why the OP posted something so simple and straightforward and no one can give a correct and straight answer?
Point out the error in my answer, please.
What the OP needs to do is:
1.Change the "private" to public. If you need to initialize the class member from an array, it needs to be accessible so you can't hide with "private".
So he has to violate encapsulation and expose the members of his class to random modification?
2.Remove any constructor you declared. The compiler will decide how to initialize the object, not you.
Tosh.
3.Change the round bracket in your parameter list to curly bracket.
This is how the working code looks like:
//...
class A
{
public:
int x;
int y;
public:
void init(int a,int b){x=a;y=b;}
void show() {printf("%d %d\r\n", x, y);}
};
int main(int argc, char* argv[])
{
A l[5] = {{1,1},{2,2},{3,3},{4,4},{5,5}};
//...
}
So why didn't you also change the "class" to "struct" and remove the access specifiers and member functions, since yours is a "C" answer, not a "C++" answer?
PaulWendt
October 28th, 2002, 11:06 AM
Originally posted by dumah
Apologies to previous poster. Didnt see your response when I began mine.
Oh don't worry about it :) If you take a couple of minutes to type
our your reply, I could have hit "Submit" in that time. The more
correct responses the merrier.
--Paul
dumah
October 28th, 2002, 11:35 AM
Originally posted by PaulWendt
Oh don't worry about it :) If you take a couple of minutes to type
our your reply, I could have hit "Submit" in that time. The more
correct responses the merrier.
--Paul
LOL - Yeah, looking at it I was really slow typing that out - work can be such a distracting place when you are trying to post on forums ;)
AnthonyMai
October 28th, 2002, 12:00 PM
Originally posted by AnthonyMai
I just don't understand why the OP posted something so simple and straightforward and no one can give a correct AND straight answer?
Graham said:
Point out the error in my answer, please.
Graham, you did not give an answer that is correct AND straight. By "straight" I mean it should be concise and elegant. You solution calls the constuctor individually. Obviously if there are 1000 elements in the array you would call constructor and destructor 100 times respectively, if there are 10000 you will call 10000 times. So it is not straight at all.
So why didn't you also change the "class" to "struct" and remove the access specifiers and member functions, since yours is a "C" answer, not a "C++" answer?
With due respect I do NOT think you can write a struct with member function in C. Structs with member functions is a feature available in C++ but not C.
AnthonyMai
October 28th, 2002, 12:14 PM
... and what if the OP wants to provide some other form of
initialization in this class? I don't think he should be forced to
use inheritance to create such a simplistic class.
"Some other form of initialization" is construct first and then initialize.
It is indeed a very simplistic class, the very fact that it can be initialized using some POD data array tells you it is a very C like simplistic class.
Just as an aside, just because you can change a bunch of things
in order to "implement a solution", it doesn't mean it's an ideal
solution. Frankly, I wouldn't want to compromise my class design
so radically like you suggest; I'd rather use any number of
alternative methods.
Since it is a simple class, please quit the talk of class design, and proper data encapsulation, and a bunch of other high level OOP concepts. These concepts may be good when the design is complicated. But they are not important here when things are rather simple and can be done in the simplest way.
[Yves : small edits]
PaulWendt
October 28th, 2002, 12:36 PM
Originally posted by AnthonyMai
Since it is a simple class, please quit the talk of class design, and proper data encapsulation, and a bunch of other high level OOP concepts. These concepts may be good when the design is complicated. But they are not important here when things are rather simple and can be done in the simplest way.
We're on a forum. When people are on forums, they typically "dumb down" their examples so that they can reproduce their COMPLICATED usages with very SIMPLE ones so that the bare concepts are explained. Because of this, it'd be nice to see a solution that would scale with complexity.
Now, I don't mind very specific solutions, but your post had NO
such disclaimer. Nowhere in your post did you say "This is only
useful for very simple classes who are basically structs". Instead,
you insult and badmouth the prior posters. Nice attitude.
--Paul
[Yves : please, be calm / small edits]
Graham
October 28th, 2002, 04:55 PM
Originally posted by AnthonyMai
Graham, you did not give an answer that is correct AND straight. By "straight" I mean it should be concise and elegant. You solution calls the constuctor individually. Obviously if there are 1000 elements in the array you would call constructor and destructor 100 times respectively, if there are 10000 you will call 10000 times. So it is not straight at all.
But there aren't 1,000 or 10,000 elements in the array, are there? There are FIVE. The original question specified a five-element array. It was declared as having five elements. It was initialised with five elements. Not 1,000, not 10,000, not 10 or 50 or 1,000,000. FIVE. Would you also explain, then, how your answer using normal C-style syntax would alleviate the problem of an array of 10,000 elements? You save one character for each initialiser - you type 60,000 characters to my 70,000. Do you really think that in the face of that, that the calling of constructors and destructors would be an issue? It wouldn't even get to that stage, because you physically would not write such an intialisation (and I'm not even going to mention optimising away the temporaries, because you'll just come up with some load of old cobblers about how it's impossible for the compiler to do it).
With due respect I do NOT think you can write a struct with member function in C. Structs with member functions is a feature available in C++ but not C.
And did I not say "remove the access specifiers and member functions"?
The fact is that the answer I gave was correct, simple and straight.
[Yves : removed a bit]
AnthonyMai
October 28th, 2002, 05:49 PM
Would you also explain, then, how your answer using normal C-style syntax would alleviate the problem of an array of 10,000 elements? You save one character for each initialiser - you type 60,000 characters to my 70,000. Do you really think that in the face of that, that the calling of constructors and destructors would be an issue?
Typing one less or one more charaters was never an issue in any programming environment. The typing is a negligible part of a programmer's job. I would never consider some code simpler or more complicated, for the consideration of the typing work load. NEVER.
You completely missed the point. The point is not that you have to spend more time typing the keyboard when an "A" is added. The point is you are making un-necessary calls to the A constructor and destructor. When you do that 1000 or 10000 times it do inflate the code size (executable code size, not source code size!) un-necessarily.
Paul McKenzie
October 28th, 2002, 06:34 PM
Originally posted by PaulWendt
What you don't seem to understand is that we're on a forum.
When people are on forums, they typically "dumb down" their
examples so that they can reproduce their COMPLICATED usages
with very SIMPLE ones so that the bare concepts are explained.
Because of this, it'd be nice to see a solution that would scale
with complexity.
Ok, I'll bite:
class AInitializer
{
public:
AInitializer(A* myA, unsigned int amount = 1)
{
std::for_each(myA, myA + amount, InitA(1));
}
};
using namespace std;
int main()
{
A l[10000];
AInitializer(l, 10000);
l[3].init(8,3);
A* p;
p = l;
p->init(3,4);
for(int i=0;i<10000;i++)
(*(p+i)).show();
}
No change of the class definition of the OP was done. An initializer object is all that's needed that initializes the values properly. Of course, there will be more elegant ways and is not the only solution.
Regards,
Paul McKenzie
AnthonyMai
October 28th, 2002, 11:43 PM
All the solutions PM, Graham and other proposed all based on some sort of manipulation of the object data.
Since these objects are initialize with some sort of constant arrays. It is reasonable to assume that those are MEANT to be const objects. You can use various member functions to access the object data, but you are NOT allowed to touch or change the object data in any way.
How would you initialize a const object array? You can't construct and then initialize, right, PM? For const objects, you have to initialize while construct.
And why construct temporary objects and destroy them, while all that matters is x gets x's value and y gets y's value, from a constant integer list.
And who says an object must needs some sort of constructor function to be constructed? For simple objects, you can construct objects WITHOUT constructor and destroy them WITHOUT destructor. Do you call any constructor when you declare an integer? Does it call a constructor 1000 times when you declare a 1000 elements integer array?
My solution is still the most elegant one since no constructor ever needs to be called. When it comes to declaring a global const object array, my solution requires not a single run time operation to be carried out.
galathaea
October 28th, 2002, 11:58 PM
One could always make a separate binary file, map (or load -- think c++ generic) that data file to memory, then just call the various data locations whatever data structures you want... except that the struct or class might have methods. If there are methods, you'll need to have some c++ runtime management to connect up the various instantiations, so in such a case, you will be incorrect Mr. Mai. If, as originally trimmed down and posted, there are no methods, then maybe my solution is more elegant than yours Mr. Mai. It keeps the code much more clean. I once defended you Mr. Mai. I thought you were just a young punk trying to prove yourself, like I was once. But I don't like you Mr. Mai. You are not nice. And not as smart as you think you are.
AnthonyMai
October 29th, 2002, 12:05 AM
[Yves : pointless post]
Yves M
October 29th, 2002, 06:18 AM
Everybody,
Please calm down. I edited some of the previous posts to remove the most flame-like replies. This is a forum where experts exchange ideas and comments and there is no need for flame-wars.
Anthony,
Check your private messages and especially the one I sent you about your message style. Apply that.
PaulWendt
October 29th, 2002, 06:21 AM
As usual, Mai is right and everyone else is wrong. Why can't the
world just accept that? I guess we're all religiously fanatic
language lawyers....
The fact of the matter is that Mai's solution is more C-like. You can
quibble semantics for all of eternity, but his solution approaches
the C language ... and it's not all that far from it. In fact, if you're
going to treat a class like that, you may as well just make it a
struct.
Also, Mai never bothered to address the fact that this simple
class might be more complicated in reality. It seems that a lot of
his defense for saying his case is justifiable is that the class is so
simple and so it doesn't need the extra complexity of a
non-compiler generated constructor. If the class becomes more
complex, however, [or if this is just an example] then his approach
won't help you out all that much.
Furthermore, if you care about information hiding, his approach
is not going to help you. Making the data members public might
work for you ... but then again, it might not. So, this approach is
not generically elegant, but it's elegant in the "specific-tailored my
solution performs 0.33% faster than yours and consumes 1.8%
less memory" line of thought.
Let's leave it at that.
--Paul
EMI_J
October 29th, 2002, 06:44 AM
the array
A I[5] = {(1,1), (2,2)...} cannot be initialised this way.
the problem is the comma operator in the brackets. (1,1) translates as 1 and the constructor for A is called with a single parameter. The second parameter default to 0 as it is declared.
for reference look at this:
int i = (1,2);
the result is
i == 2
sorry for annoying you.
PaulWendt
October 29th, 2002, 06:56 AM
Originally posted by EMI_J
the array
A I[5] = {(1,1), (2,2)...} cannot be initialised this way.
the problem is the comma operator in the brackets. (1,1) translates as 1 and the constructor for A is called with a single parameter. The second parameter default to 0 as it is declared.
for reference look at this:
int i = (1,2);
the result is
i == 2
sorry for annoying you.
It's not an array of int's, though; it's an array of A's. A has a
constructor that takes two arguments; an int has no such
constructor.
--Paul
Graham
October 29th, 2002, 10:57 AM
...ah, but A is not a POD, and the compiler doesn't know that the "(n,n)" list should refer to the constructor for A. Which is why you need to be explicit and put "A(n,n)". But then again, that's a hopelessly wrong-headed and inelegant thing to do, isn't it? ;)
EMI_J
October 29th, 2002, 11:15 AM
yes, Graham, you are absolutely right
for Paul Wendt:
(1, 1) translates to 1 then to int(1) then to A(1, 0)
PaulWendt
October 29th, 2002, 11:44 AM
Originally posted by EMI_J
yes, Graham, you are absolutely right
for Paul Wendt:
(1, 1) translates to 1 then to int(1) then to A(1, 0)
Sorry. I guess I misunderstood you since someone already had
said this. I thought you were quoting THAT person telling them
that they were incorrect.
AnthonyMai
October 29th, 2002, 12:07 PM
Furthermore, if you care about information hiding, his approach
is not going to help you. Making the data members public might
work for you ... but then again, it might not. So, this approach is
not generically elegant, but it's elegant in the "specific-tailored my
solution performs 0.33% faster than yours and consumes 1.8% less memory" line of thought.
Let's leave it at that.
--Paul
Where did you get the 0.33% and 1.8% figure? Are you sure it is not 0.1%, or more, or less?
If you want numbers here are the hard numbers.
class A
{
public:
int x;
int y;
public:
A(int a, int b) {x = a; y = b;}
void init(int a, int b){x=a;y=b;}
void show() const {printf("%d %d\r\n", x, y);}
};
class B
{
public:
int x;
int y;
public:
void init(int a, int b){x=a;y=b;}
void show() const {printf("%d %d\r\n", x, y);}
};
const A A_array[5] = {A(1,1),A(2,2),A(3,3),A(4,4),A(5,5)};
const B B_array[5] = {{1,1},{2,2},{3,3},{4,4},{5,5}};
Here is what my solution, B_array, looks like when compiled:
So which one is more elegant? Is it JUST 0.33% faster and takes 1.8% less memory?
kuphryn
October 29th, 2002, 12:22 PM
In general data structure and especially C++ OOP, data encapsulation is essential. Otherwise, consider a structure.
Kuphryn
galathaea
October 29th, 2002, 12:24 PM
So which one is more elegant?
If all we are doing is setting up an array of constant struct-like objects, I think my solution is better.
// load data file to pSomewhere
A *myAArray;
myAArray = pSomewhere;
It is scalable and keeps your code clean. You always have to have a source for your consts, but if it is large, move it to some data file. The OS will have to map your data in if you don't, so there will be no real performance hit doing it yourself explicitly (maybe one extra page or something). Of course, it would be best to wrap up the type conversion in a typesafe manner for large projects, etc. but that would be normal c++ design standards.
Peace all.
PaulWendt
October 29th, 2002, 12:58 PM
Originally posted by AnthonyMai
Where did you get the 0.33% and 1.8% figure? Are you sure it is not 0.1%, or more, or less?
So which one is more elegant? Is it JUST 0.33% faster and takes 1.8% less memory?
Mai, I made the numbers up. In fact, I enclosed that whole
portion of my sentence in double quotes to indicate that it
was not a definite thing, but rather a concept:
[QUOTE]
So, this approach is not generically elegant, but it's elegant in
the "specific-tailored my solution performs 0.33% faster than
yours and consumes 1.8% less memory" line of thought.
[/QUOTE
Whether you see this now or not is irrelevant. It's already
obvious that your solution will be faster; is it BETTER though?
Should your changes be made everywhere? Should they even be
made to a class that is this simple? I'd argue no. Unless you
really need every bit of performance, I wouldn't bother with
what you suggest.
Like I said earlier, you can quibble with ridiculous semantics all
you want, but you'll never admit to the fact that your solution
simply isn't suitable for large-scale reuse. Fine, your solution
might have some use in some limited circumstances, but it's
certainly not for the vast majority of cases.
The thing that kills me is that you had the audacity to lambast
the responses of others for not being "straight" [which you define
differently than any other english-speaker].
--Paul
Gabriel Fleseriu
October 30th, 2002, 02:26 AM
For the records:
I compiled following code under VC++6.0, release mode, optimized for maximum speed, debug information enabled.
#include <iostream>
class A
{
public:
int x;
int y;
public:
A(int a, int b):x(a),y(b){}
void init(int a, int b){x=a;y=b;}
void show() const {printf("%d %d\r\n", x, y);}
};
class B
{
public:
int x;
int y;
public:
void init(int a, int b){x=a;y=b;}
void show() const {printf("%d %d\r\n", x, y);}
};
int main(int argc, char* argv[])
{
int i;
A A_array[5] = {A(1,1),A(2,2),A(3,3),A(4,4),A(5,5)};
B B_array[5] = {{1,1},{2,2},{3,3},{4,4},{5,5}};
for(i=0; i<5; i++){
std::cout<<A_array[i].x+B_array[i].y<<std::endl;
}
return 0;
}
The loop is there only to simulate a non-trivial program - or else the compiler would have optimized out both A_array and B_array. The disassembly is this:
I think I don't have to comment on this any further.
Paul McKenzie
October 30th, 2002, 11:43 AM
Well, looks like another faux pas by Mai.
This and other threads reminds me of those old Road Runner / Wile E. Coyote cartoons where the Coyote (a self-proclaimed "super genius") tries to catch the Road Runner with all sorts of inventions, gadgets, contraptions, etc. He never catches the Road Runner, instead all of the inventions and gadgets backfire on the Coyote.
Just a thought.
Regards,
Paul McKenzie
AnthonyMai
October 30th, 2002, 12:02 PM
For the records:
I compiled following code under VC++6.0, release mode, optimized for maximum speed, debug information enabled.
//..
int main(int argc, char* argv[])
{
int i;
A A_array[5] = {A(1,1),A(2,2),A(3,3),A(4,4),A(5,5)};
B B_array[5] = {{1,1},{2,2},{3,3},{4,4},{5,5}};
//...
The truth of the record is, we are talking about objects initialize using CONSTANTS and objects that is meants to provide access to those constant numbers so they stay constant once initialize.
Such objects should be put in the heap memory. That means they should NOT be declared as local variables that sit in the stack. They should be declared as either globals or static variables within functions. Declaring them as regular variables within the function scope forces them to be put on the stack and forces them to be initialized again and again for each iteration of function calls.
[Yves : removed useless bit
Antony, you read my warning, so apply it]
Yves M
October 30th, 2002, 12:35 PM
Anthony,
Whether or not the variables are supposed to be constants or statics or whatever has not been specified by the OP, so let's not assume that.
And by the way, when you define a global constant, it doesn't get put into the heap ;)
Andreas Masur
October 30th, 2002, 12:50 PM
May I suggest to close this thread at this point. This discussion most-likely does not have much to do with the original question but rather turned into a religious and to my mind senseless discussion like it happens with most of the threads one specific guy is involved.
The answer(s) were given a long time ago and I really do not see any need to go on with this thread since there will never be a reasonable agreement on this topic.
AnthonyMai
October 30th, 2002, 12:57 PM
Whether or not the variables are supposed to be constants or statics or whatever has not been specified by the OP, so let's not assume that.
I am not ASSUMING that. I am giving advice that under such circumstance it is best to declare a constant global array or at least make it static within the function, unless the OP has some specific reasons not to. And I have not see any one presenting a reason not to.
And by the way, when you define a global constant, it doesn't get put into the heap
It does when you are talking about global constant arrays. If it is just a const int, double or char, the compiler may just compile it in place instead of allocating storage for the variable in the heap. But when it is an array, the compiler would rather prefer to leave it in the heap, instead of compile them directly in place.
Yves M
October 30th, 2002, 01:58 PM
Originally posted by AnthonyMai
I am not ASSUMING that. I am giving advice that under such circumstance it is best to declare a constant global array or at least make it static within the function, unless the OP has some specific reasons not to. And I have not see any one presenting a reason not to.
Fine, it wasn't clear to me that this was a suggestion ;)
It does when you are talking about global constant arrays. If it is just a const int, double or char, the compiler may just compile it in place instead of allocating storage for the variable in the heap. But when it is an array, the compiler would rather prefer to leave it in the heap, instead of compile them directly in place.
And different compilers might handle different cases differently ;)
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.