Forward declaration in C++ not working

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #16
    FYI Jos these are the errors

    childClass.h:13 : error: ISO C++ forbids declaration of ‘parentCla ss’ with no type
    childClass.h:13 : error: expected ‘;’ before ‘*’ token
    childClass.h:15 : error: expected `)' before ‘*’ token

    when compiling parentClass.cpp

    Comment

    • JosAH
      Recognized Expert MVP
      • Mar 2007
      • 11453

      #17
      Originally posted by Banfa
      FYI Jos these are the errors

      childClass.h:13 : error: ISO C++ forbids declaration of ‘parentClass’ with no type
      childClass.h:13 : error: expected ‘;’ before ‘*’ token
      childClass.h:15 : error: expected `)' before ‘*’ token

      when compiling parentClass.cpp
      Ah, I get it: in child.h the parentClass should be declared and in parent.h the childClass should be declared (that's what this entire discussion started).

      The two next lines of error messages are just bogus given the first error.

      kind regards,

      Jos

      edit: @OP: don't mix up 'definition' with 'declaration'; i.e. simply declare the existense of the other class in your .h files

      Comment

      • ducttape
        New Member
        • May 2009
        • 15

        #18
        It's actually quite an interesting discussion, I always did wonder it was bad programming form on my part but I do it all the time in Java and C#: for the class that instantiates another class to pass itself through as a parameter so that the second class can refer to it as its parent. It's a really neat trick which saves bucketloads of code and I'd imagine saves bucketloads of memory. But if C++ doesn't allow it easily perhaps that's indicative of poor form.

        I'm going to try my third inbetween class method and see how that works. I'll hopefully have it done by tomorrow and I'll report back. Till then, take care guys thanks for all your help.

        Comment

        • JosAH
          Recognized Expert MVP
          • Mar 2007
          • 11453

          #19
          Originally posted by ducttape
          It's actually quite an interesting discussion, I always did wonder it was bad programming form on my part but I do it all the time in Java and C#: for the class that instantiates another class to pass itself through as a parameter so that the second class can refer to it as its parent. It's a really neat trick which saves bucketloads of code and I'd imagine saves bucketloads of memory. But if C++ doesn't allow it easily perhaps that's indicative of poor form.

          I'm going to try my third inbetween class method and see how that works. I'll hopefully have it done by tomorrow and I'll report back. Till then, take care guys thanks for all your help.
          You don't need an inbetween class; define your classes in a .h file and only make the class refer to the other class as a reference or a pointer. Declare the existence of the other class before you define the class that belongs in your .h header file.

          Also guard your two header files to prevent the preprocessor to dive in its recursion when two header files include eachother.

          In your .cpp files you are free to do what you want after including the two header files. The classes are defined in the header files already.

          Don't make a simple mistake of yours lead you to a complicated (artificial) solution. It's just the compiler that is too stupid to understand that an arbitrary word is supposed to be the name of a class. C++ is not Java.

          kind regards,

          Jos

          ps. I cooked up a little skeleton:

          Code:
          #ifndef CHILD_H
          #define CHILD_H
          
          // tell the compiler this class exists:
          class parentClass;
          
          // define your class here:
          class childClass {
             // only refer to the parent class as
             // parentClass* aPointerToParent; or
             // parentClass& aParentReference
          }
          
          #endif
          Do the same for your parentClass (childClass <--> parentClass) and program away in your parent.cpp and child.cpp files where both classes are defined (because of the inclusion of the .h files).

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #20
            Originally posted by JosAH
            It's just the compiler that is too stupid to understand that an arbitrary word is supposed to be the name of a class. C++ is not Java.
            Are you saying that Java does treat any arbitrary keyword as a class (or class name)?

            More seriously does Java void this problem because it does >1 pass compilation and therefore has visibility of all class names after the first pass?

            Comment

            • JosAH
              Recognized Expert MVP
              • Mar 2007
              • 11453

              #21
              Originally posted by Banfa
              Are you saying that Java does treat any arbitrary keyword as a class (or class name)?

              More seriously does Java void this problem because it does >1 pass compilation and therefore has visibility of all class names after the first pass?
              Nope, not saying that but the Java compiler is able to peek in compiled code; just enough to judge the code to be compiled for validity. That's where Java's 'classpath' comes in and that's why a lot of beginners are having trouble with it: they expect a certain level of psychic abilities from the compiler ;-)

              kind regards,

              Jos

              Comment

              • ducttape
                New Member
                • May 2009
                • 15

                #22
                It's working with the forward declaration of childClass instead of the #include childClass. Thanks so much for your patience. In retrospect I'm embarassed that I too expected psychic abilities from the compiler. It just seemed so natural.

                One of the starkest differences is that Java's variables are pointers by default. To create a new instance you actually have to use the "new" keyword. It seems to me to be a much more efficient way of doing things.

                For anyone else reading this thread, if you change the code in the first block in post 10, line 6, from

                #include "childClass .h"

                to

                class childClass;

                it works. I still wonder about the quality of my code using a trick like that but it seems to work fine. Thanks again Banfa and JosAH you've been most kind.

                Comment

                • JosAH
                  Recognized Expert MVP
                  • Mar 2007
                  • 11453

                  #23
                  Originally posted by ducttape
                  One of the starkest differences is that Java's variables are pointers by default. To create a new instance you actually have to use the "new" keyword. It seems to me to be a much more efficient way of doing things.
                  C++ can do that too but C++ carries a C heritage where objects can have value semantics, i.e. you don't just have a pointer (reference) to an object, as in Java, but you can plough your way through an object itself, anyway you want. That heritage is a mixed blessing.

                  kind regards,

                  Jos

                  ps. remember: everything needs to be declared before you can even mention it in other code. A definition counts as a declaration.

                  Comment

                  • ducttape
                    New Member
                    • May 2009
                    • 15

                    #24
                    I spoke too soon. I forgot my code example doesn't actually have a child belonging to the parent. If I try to add one, even if I forward declare childClass, I get error C2079: 'parentClass::c ' uses undefined class 'childClass'. This is from simply adding a childClass variable to parentClass, not even from instantiating it.

                    Comment

                    • JosAH
                      Recognized Expert MVP
                      • Mar 2007
                      • 11453

                      #25
                      Originally posted by ducttape
                      I spoke too soon. I forgot my code example doesn't actually have a child belonging to the parent. If I try to add one, even if I forward declare childClass, I get error C2079: 'parentClass::c ' uses undefined class 'childClass'. This is from simply adding a childClass variable to parentClass, not even from instantiating it.
                      Here we go again: declare everything before you use it; if you just declare a class you can't use any of its members (because the compiler doesn't know about them), nor can you use the size of an object of the class. The guard mechanism as well as the forward declaration of the class(es) are enough to solve your problem.

                      kind regards,

                      Jos

                      Comment

                      • ducttape
                        New Member
                        • May 2009
                        • 15

                        #26
                        Thanks for your patience. Everything was declared and I was not using anything. I have guard mechanisms around all of my classes. I forward declared childClass and then added a childClass variable to parentClass. In childClass, I forward declared parentClass and added a parentClass variable to childClass. So far I have not defined anything or tried to use any of its members. If simply adding a variable requires you to define the class then logically the problem is unsolvable because declaring the variables is part of each classes definition.

                        I suspect you are right though, which means there must be some other error in my code that is causing the problem. I will try to figure it out when I have more time, unfortunately I need to get on with this project so I'm using my horrible artificial solution wth a third class. At least this way I never have to use "this" references or anything.

                        If I ever get it working I'll post my findings here. Till then, then.

                        Comment

                        • Banfa
                          Recognized Expert Expert
                          • Feb 2006
                          • 9067

                          #27
                          This is what we have been through in posts 1-6 of this thread.

                          The forward declaration does not allow you to declare a instance of the class but does allow you to declare a pointer to reference to the class.

                          You can then instantiate this pointer/reference using new in the class constructor.

                          You can do it where you define the constructor but not where you declare the class because the cpp file holding the member function definitions can have visibility of the declarations of both classes but the class declarations in the 2 headers can not have mutual visibility of each other.

                          That is if the childClass declaration is visible to the parentClass then the parentClass declaration can not be visible to the childClass. But the childClass can have visibility of a forward declaration of the parentClass name allowing it to declare pointers and references.

                          Comment

                          Working...