Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Nested structs problem [modified]

Nested structs problem [modified]

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestion
19 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    manchukuo
    wrote on last edited by
    #1

    Hi there i am currently facing this problem. I use forward declaration to declare both structs but when doing an assignment to the struct it complains that is undefined.Ex. i have this structs:struct A; struct B; struct A { int lolipops; B* candy; A(B* ptr) { lolipops = 0; candy = ptr; } action(int pass) { candy->gums = pass;//this is where i get the error of undefined type 'B' } }; 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' } };
    This is a sample not used currently by me but it ilustrates the problem. Can someone tell me what is wrong?

    modified on Sunday, February 13, 2011 4:54 PM

    L L N 3 Replies Last reply
    0
    • M manchukuo

      Hi there i am currently facing this problem. I use forward declaration to declare both structs but when doing an assignment to the struct it complains that is undefined.Ex. i have this structs:struct A; struct B; struct A { int lolipops; B* candy; A(B* ptr) { lolipops = 0; candy = ptr; } action(int pass) { candy->gums = pass;//this is where i get the error of undefined type 'B' } }; 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' } };
      This is a sample not used currently by me but it ilustrates the problem. Can someone tell me what is wrong?

      modified on Sunday, February 13, 2011 4:54 PM

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      Sorry, my original answer does not work. Something strange about this post, the forward declarations did not show in the posted question. Please also use <pre></pre> tags round your code - set by the code block button. The forward declaration will only help you to have pointers to B types in structure A. You will not be able to refer to any of the variables or methods of B as they have not been defined at that point. You will need to modify your design to resolve your problem.

      I must get a clever new signature for 2011.

      modified on Sunday, February 13, 2011 4:49 PM

      M 1 Reply Last reply
      0
      • L Lost User

        Sorry, my original answer does not work. Something strange about this post, the forward declarations did not show in the posted question. Please also use <pre></pre> tags round your code - set by the code block button. The forward declaration will only help you to have pointers to B types in structure A. You will not be able to refer to any of the variables or methods of B as they have not been defined at that point. You will need to modify your design to resolve your problem.

        I must get a clever new signature for 2011.

        modified on Sunday, February 13, 2011 4:49 PM

        M Offline
        M Offline
        manchukuo
        wrote on last edited by
        #3

        Can you tell me how to solve it. What it needs to be modified?, Please

        L 1 Reply Last reply
        0
        • M manchukuo

          Hi there i am currently facing this problem. I use forward declaration to declare both structs but when doing an assignment to the struct it complains that is undefined.Ex. i have this structs:struct A; struct B; struct A { int lolipops; B* candy; A(B* ptr) { lolipops = 0; candy = ptr; } action(int pass) { candy->gums = pass;//this is where i get the error of undefined type 'B' } }; 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' } };
          This is a sample not used currently by me but it ilustrates the problem. Can someone tell me what is wrong?

          modified on Sunday, February 13, 2011 4:54 PM

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Not sure it suffices, however within the structs, I would use struct B* instead of just B*, and likewise for A*. :)

          Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

          Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

          M 1 Reply Last reply
          0
          • L Luc Pattyn

            Not sure it suffices, however within the structs, I would use struct B* instead of just B*, and likewise for A*. :)

            Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

            Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

            M Offline
            M Offline
            manchukuo
            wrote on last edited by
            #5

            Nope i tried your suggestion and doesn't work either :sigh:

            L 1 Reply Last reply
            0
            • M manchukuo

              Nope i tried your suggestion and doesn't work either :sigh:

              L Offline
              L Offline
              Luc Pattyn
              wrote on last edited by
              #6

              you replaced all of them? it should never throw two errors, when the compiler reaches the second struct it knows all there is to know about the first one. :)

              Luc Pattyn [Forum Guidelines] [My Articles] Nil Volentibus Arduum

              Please use <PRE> tags for code snippets, they preserve indentation, improve readability, and make me actually look at the code.

              1 Reply Last reply
              0
              • M manchukuo

                Hi there i am currently facing this problem. I use forward declaration to declare both structs but when doing an assignment to the struct it complains that is undefined.Ex. i have this structs:struct A; struct B; struct A { int lolipops; B* candy; A(B* ptr) { lolipops = 0; candy = ptr; } action(int pass) { candy->gums = pass;//this is where i get the error of undefined type 'B' } }; 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' } };
                This is a sample not used currently by me but it ilustrates the problem. Can someone tell me what is wrong?

                modified on Sunday, February 13, 2011 4:54 PM

                N Offline
                N Offline
                Niklas L
                wrote on last edited by
                #7

                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.

                home

                L 1 Reply Last reply
                0
                • M manchukuo

                  Can you tell me how to solve it. What it needs to be modified?, Please

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  There is no fix for what you want, since you have effectively got circular dependencies: A refers to B and B refers to A 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.

                  1 Reply Last reply
                  0
                  • N Niklas L

                    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.

                    home

                    L Offline
                    L Offline
                    Lost User
                    wrote on last edited by
                    #9

                    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.

                    N 1 Reply Last reply
                    0
                    • L Lost User

                      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.

                      N Offline
                      N Offline
                      Niklas L
                      wrote on last edited by
                      #10

                      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?

                      home

                      M L 2 Replies Last reply
                      0
                      • N Niklas L

                        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?

                        home

                        M Offline
                        M Offline
                        manchukuo
                        wrote on last edited by
                        #11

                        :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

                        L 1 Reply Last reply
                        0
                        • N Niklas L

                          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?

                          home

                          L Offline
                          L Offline
                          Lost User
                          wrote on last edited by
                          #12

                          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.

                          N 1 Reply Last reply
                          0
                          • M manchukuo

                            :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

                            L Offline
                            L Offline
                            Lost User
                            wrote on last edited by
                            #13

                            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 of struct A which contained a struct B*; all fine up to this point. struct A then contained a reference to one of struct 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.

                            M 1 Reply Last reply
                            0
                            • L Lost User

                              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 of struct A which contained a struct B*; all fine up to this point. struct A then contained a reference to one of struct 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.

                              M Offline
                              M Offline
                              manchukuo
                              wrote on last edited by
                              #14

                              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:

                              N S 2 Replies Last reply
                              0
                              • L Lost User

                                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.

                                N Offline
                                N Offline
                                Niklas L
                                wrote on last edited by
                                #15

                                I know you know. There was just great confusion. :)

                                home

                                1 Reply Last reply
                                0
                                • M manchukuo

                                  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:

                                  N Offline
                                  N Offline
                                  Niklas L
                                  wrote on last edited by
                                  #16

                                  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;
                                  }

                                  home

                                  M 1 Reply Last reply
                                  0
                                  • M manchukuo

                                    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:

                                    S Offline
                                    S Offline
                                    Stefan_Lang
                                    wrote on last edited by
                                    #17

                                    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;

                                    M 1 Reply Last reply
                                    0
                                    • N Niklas L

                                      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;
                                      }

                                      home

                                      M Offline
                                      M Offline
                                      manchukuo
                                      wrote on last edited by
                                      #18

                                      this way works perfectly so i have to implement the non-constructor code outside the struct body and it worked, Thanks ;P

                                      1 Reply Last reply
                                      0
                                      • S Stefan_Lang

                                        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;

                                        M Offline
                                        M Offline
                                        manchukuo
                                        wrote on last edited by
                                        #19

                                        Yes it helps, i now understand more of the problem here so this is compiler dependent then. Thanks for your time i have learned from all you!!

                                        1 Reply Last reply
                                        0
                                        Reply
                                        • Reply as topic
                                        Log in to reply
                                        • Oldest to Newest
                                        • Newest to Oldest
                                        • Most Votes


                                        • Login

                                        • Don't have an account? Register

                                        • Login or register to search.
                                        • First post
                                          Last post
                                        0
                                        • Categories
                                        • Recent
                                        • Tags
                                        • Popular
                                        • World
                                        • Users
                                        • Groups