Nested structs problem [modified]
-
There is no fix for what you want, since you have effectively got circular dependencies:
A
refers toB
andB
refers toA
so one of them will be undeclared in the declaration of the other. You cannot make this work and need to redesign your program to remove such dependencies.I must get a clever new signature for 2011.
-
Keep declaration in a header file. That will make the forward declarations work. Then put the implementation in a cpp-file. Here you can do these kinds of things since both structs are declared properly. Btw, I still think you should reconsider your design if possible.
-
That won't make any difference as one of them will still be undefined in the declaration of the other. See my answer above.
I must get a clever new signature for 2011.
The following is perfectly legal
struct A;
struct B;struct A
{
int lolipops;
B* candy;A(B* ptr);
void action(int pass);
};struct B{
int gums;
A* candy;B(A* ptr);
void action(int pass);
};The compiler needs to know the size of a class when it's compiling it. That's the major reason why things must be declared in advance. In this case, the dependency size is known since the member is a pointer to the forward declared class. You can of course not use that pointer until the thing it points to has been properly declared, and that's the problem in the OP. Edit: When I answered, the members were actually pointers to the other class. That might have changed since your reply?
-
The following is perfectly legal
struct A;
struct B;struct A
{
int lolipops;
B* candy;A(B* ptr);
void action(int pass);
};struct B{
int gums;
A* candy;B(A* ptr);
void action(int pass);
};The compiler needs to know the size of a class when it's compiling it. That's the major reason why things must be declared in advance. In this case, the dependency size is known since the member is a pointer to the forward declared class. You can of course not use that pointer until the thing it points to has been properly declared, and that's the problem in the OP. Edit: When I answered, the members were actually pointers to the other class. That might have changed since your reply?
:rolleyes: OK so declaring in the .h and implementing in the .cpp works but it doesn't if your declare/implement in the same place. Someone knows why? And also i will to know how to improve the design i want to know what is wrong and to improve. Thanks
-
The following is perfectly legal
struct A;
struct B;struct A
{
int lolipops;
B* candy;A(B* ptr);
void action(int pass);
};struct B{
int gums;
A* candy;B(A* ptr);
void action(int pass);
};The compiler needs to know the size of a class when it's compiling it. That's the major reason why things must be declared in advance. In this case, the dependency size is known since the member is a pointer to the forward declared class. You can of course not use that pointer until the thing it points to has been properly declared, and that's the problem in the OP. Edit: When I answered, the members were actually pointers to the other class. That might have changed since your reply?
-
:rolleyes: OK so declaring in the .h and implementing in the .cpp works but it doesn't if your declare/implement in the same place. Someone knows why? And also i will to know how to improve the design i want to know what is wrong and to improve. Thanks
It has nothing to do with it being defined in the header or the cpp file. The issue was with referring to struct variables that have not been declared. In your original question you had a forward declaration of
struct B
. You then had a declaration ofstruct A
which contained astruct B*
; all fine up to this point.struct A
then contained a reference to one ofstruct B
's variables, which had not yet been defined, hence your compiler error. If it works now, then you must have changed something.I must get a clever new signature for 2011.
-
It has nothing to do with it being defined in the header or the cpp file. The issue was with referring to struct variables that have not been declared. In your original question you had a forward declaration of
struct B
. You then had a declaration ofstruct A
which contained astruct B*
; all fine up to this point.struct A
then contained a reference to one ofstruct B
's variables, which had not yet been defined, hence your compiler error. If it works now, then you must have changed something.I must get a clever new signature for 2011.
I did only changed the following, i just migrate the implementation from the .h to .cpp and it worked. Look this is what i had originaly at first in a .h, which is the way it did not worked //base.h file
//forward decl
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr)
{
lolipops = 0;
candy = ptr;
}action(int pass)
{
candy->gums = pass;
}
};struct B
{
int gums;
A* candy;B(A* ptr)
{
gums = 0;
candy = ptr;
}action(int pass)
{
candy->lolipops = pass;//this is where i get the error of undefined type 'A'
}
};The way it worked is the following i only declared the structs in .h and implemented it on the .cpp file like this: .h file
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr);
void action(int pass);
};struct B
{
int gums;
A* candy;
B(A* ptr);
void action(int pass);
};in .cpp file
#include "base.h"
A::A(B* ptr)
{}
void A::action(int pass)
{
candy->gums = pass;
}B::B(A* ptr)
{
candy = ptr;
}void B::action(int pass)
{
candy->lolipops = pass;
}and that is what changed, so trying to do everything in the .h file does not work :omg:
-
Yes, I know it's legal, but that is not what the OP had in his/her definitions.
I must get a clever new signature for 2011.
-
I did only changed the following, i just migrate the implementation from the .h to .cpp and it worked. Look this is what i had originaly at first in a .h, which is the way it did not worked //base.h file
//forward decl
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr)
{
lolipops = 0;
candy = ptr;
}action(int pass)
{
candy->gums = pass;
}
};struct B
{
int gums;
A* candy;B(A* ptr)
{
gums = 0;
candy = ptr;
}action(int pass)
{
candy->lolipops = pass;//this is where i get the error of undefined type 'A'
}
};The way it worked is the following i only declared the structs in .h and implemented it on the .cpp file like this: .h file
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr);
void action(int pass);
};struct B
{
int gums;
A* candy;
B(A* ptr);
void action(int pass);
};in .cpp file
#include "base.h"
A::A(B* ptr)
{}
void A::action(int pass)
{
candy->gums = pass;
}B::B(A* ptr)
{
candy = ptr;
}void B::action(int pass)
{
candy->lolipops = pass;
}and that is what changed, so trying to do everything in the .h file does not work :omg:
You can make it work even if you put it all in the .h file
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr) {}
inline void action(int pass);
};struct B
{
int gums;
A* candy;
B(A* ptr) {}
inline void action(int pass);
};inline void A::action(int pass)
{
candy->gums = pass;
}inline void B::action(int pass)
{
candy->lolipops = pass;
} -
I did only changed the following, i just migrate the implementation from the .h to .cpp and it worked. Look this is what i had originaly at first in a .h, which is the way it did not worked //base.h file
//forward decl
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr)
{
lolipops = 0;
candy = ptr;
}action(int pass)
{
candy->gums = pass;
}
};struct B
{
int gums;
A* candy;B(A* ptr)
{
gums = 0;
candy = ptr;
}action(int pass)
{
candy->lolipops = pass;//this is where i get the error of undefined type 'A'
}
};The way it worked is the following i only declared the structs in .h and implemented it on the .cpp file like this: .h file
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr);
void action(int pass);
};struct B
{
int gums;
A* candy;
B(A* ptr);
void action(int pass);
};in .cpp file
#include "base.h"
A::A(B* ptr)
{}
void A::action(int pass)
{
candy->gums = pass;
}B::B(A* ptr)
{
candy = ptr;
}void B::action(int pass)
{
candy->lolipops = pass;
}and that is what changed, so trying to do everything in the .h file does not work :omg:
Basically it all comes down to the compiler being incapable of reading ahead: the moment you do something you have to make sure that all neccessary defintions have been made before:
struct A; // 'A' is a symbol used to declare a struct type some time later
struct B; // same for 'B'
struct A { // here starts the declaration of A (this makes the forward declaration of A redundant!)
int gummy;
B* myb; // this is a pointer - since all pointers are of same size, no need to more about B here
A() : myb(0) {} // initialize a pointer to an unknown type to 0 is not a problem either
void set(B* b) {
myb = b; // again no problem - a pointer is a pointer is a pointer
gummy = b->bears; // error: compiler does not know about bears at this point!
}
};
struct B {
int bears; // now, had the compiler only known about this before ...
A* mya; // ok, just a pointer here
B() : mya(0) {} // same boring stuff
void set(A* a) {
mya = a; // pointer stuff, no worries
bears = a->gummy; // error: compiler hasn't seen a *valid* declaration of struct A yet, and thus doesn't know about gummy
}
};You can skip the forward declaration of A here, but you have to move the implemetation of A::set() to a later point in your code, so the compiler gets a chance to read the declaration of B first:
struct B; // forward declaration for 'B' (none needed for A)
struct A { // here starts the declaration of A (this makes the forward declaration of A redundant!)
int gummy;
B* myb; // this is a pointer - since all pointers are of same size, no need to more about B here
A() : myb(0) {} // initialize a pointer to an unknown type to 0 is not a problem either
void set(B* b); // ok: just a prototype declaration, using a pointer to an as of yet undefined struct
}; // end of declaration of struct A: from now on, the compiler knows the full scope of A!
struct B {
int bears;
A* mya; // ok, just a pointer here
B() : mya(0) {} // same boring stuff
void set(A* a) {
mya = a; // pointer stuff, no worries
bears = a->gummy; // ok: compiler has seen the declaration of struct A, and thus knows about gummy
}
}; // end of declaration of struct B: from now on, the compiler knows the full scope of B!
void A::set( B* b )
{
myb = b; -
You can make it work even if you put it all in the .h file
struct A;
struct B;struct A
{
int lolipops;
B* candy;
A(B* ptr) {}
inline void action(int pass);
};struct B
{
int gums;
A* candy;
B(A* ptr) {}
inline void action(int pass);
};inline void A::action(int pass)
{
candy->gums = pass;
}inline void B::action(int pass)
{
candy->lolipops = pass;
} -
Basically it all comes down to the compiler being incapable of reading ahead: the moment you do something you have to make sure that all neccessary defintions have been made before:
struct A; // 'A' is a symbol used to declare a struct type some time later
struct B; // same for 'B'
struct A { // here starts the declaration of A (this makes the forward declaration of A redundant!)
int gummy;
B* myb; // this is a pointer - since all pointers are of same size, no need to more about B here
A() : myb(0) {} // initialize a pointer to an unknown type to 0 is not a problem either
void set(B* b) {
myb = b; // again no problem - a pointer is a pointer is a pointer
gummy = b->bears; // error: compiler does not know about bears at this point!
}
};
struct B {
int bears; // now, had the compiler only known about this before ...
A* mya; // ok, just a pointer here
B() : mya(0) {} // same boring stuff
void set(A* a) {
mya = a; // pointer stuff, no worries
bears = a->gummy; // error: compiler hasn't seen a *valid* declaration of struct A yet, and thus doesn't know about gummy
}
};You can skip the forward declaration of A here, but you have to move the implemetation of A::set() to a later point in your code, so the compiler gets a chance to read the declaration of B first:
struct B; // forward declaration for 'B' (none needed for A)
struct A { // here starts the declaration of A (this makes the forward declaration of A redundant!)
int gummy;
B* myb; // this is a pointer - since all pointers are of same size, no need to more about B here
A() : myb(0) {} // initialize a pointer to an unknown type to 0 is not a problem either
void set(B* b); // ok: just a prototype declaration, using a pointer to an as of yet undefined struct
}; // end of declaration of struct A: from now on, the compiler knows the full scope of A!
struct B {
int bears;
A* mya; // ok, just a pointer here
B() : mya(0) {} // same boring stuff
void set(A* a) {
mya = a; // pointer stuff, no worries
bears = a->gummy; // ok: compiler has seen the declaration of struct A, and thus knows about gummy
}
}; // end of declaration of struct B: from now on, the compiler knows the full scope of B!
void A::set( B* b )
{
myb = b;