Thread: Two Classes Referring to each other

  1. #1
    Student
    Join Date
    Oct 2005
    Posts
    6

    Two Classes Referring to each other

    I have two classes referring to each other, but when i try to compile the code I get these errors,

    jw-mytest$g++ -o mytest foo.cpp boo.cpp
    foo.cpp: In member function 'boo* foo::getBoo()':
    foo.cpp:4: error: invalid use of undefined type 'struct boo'
    foo.h:3: error: forward declaration of 'struct boo'

    The code is below:

    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    #include "foo.h"
    class boo
    {
      public:
        boo();
        foo* getFoo();
    };
    #endif
    
    
    //FILE - boo.cpp
    #include "boo.h"
    boo::boo() { }
    foo* boo::getFoo() { return new foo(); }
    
    
    //FILE - foo.h
    #ifndef FOO_H
    #define FOO_H
    class boo;
    class foo
    {
      public:
        foo();
        boo* getBoo();
    };
    #endif
    
    
    //FILE - foo.cpp
    #include "foo.h"
    foo::foo() { }
    boo* foo::getBoo() { return new boo(); }
    Is it possible to even to do this?

  2. #2
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    File: common.h
    Code:
    #ifndef COMMON_H_
    #define COMMON_H_
    class boo;
    class foo;
    #endif
    file: foo.h
    Code:
    #ifndef FOO_H_
    #define FOO_H_
    class foo
    {
      boo* bar;
    };
    #endif
    file: bar.h
    Code:
    #ifndef BAR_H_
    #define BAR_H_
    class bar
    {
      foo* baz;
    };
    #endif
    Basically you setup a common header file to declare the classes.

  3. #3
    Student
    Join Date
    Oct 2005
    Posts
    6
    How do I use the the common header file?

  4. #4
    Student
    Join Date
    Oct 2005
    Posts
    6
    Has anyone got any ideas?

  5. #5
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    since you use only pointers to the other class your case is rather simple. just put a forward declaration to class foo into boo.h
    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    #include "foo.h"
    class foo;
    class boo
    {
      public:
        boo();
        foo* getFoo();
    };
    #endif
    It's a bit more difficult if you want to ebbed an object of the other class in one of the classes because then everything depends on the order of the inludes in the implementation files-
    Kurt

  6. #6
    Student
    Join Date
    Oct 2005
    Posts
    6
    That worked perfectly. Thank you.

  7. #7
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    Quote Originally Posted by jwong78
    How do I use the the common header file?
    #include common.h in both header files. Sorry forgot those

  8. #8
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    Quote Originally Posted by ZuK
    since you use only pointers to the other class your case is rather simple. just put a forward declaration to class foo into boo.h
    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    #include "foo.h"
    class foo;
    class boo
    {
      public:
        boo();
        foo* getFoo();
    };
    #endif
    eh? why are you including foo.h and forward declaring class foo?

    Actually the OP was really close at the beginning! all you needed to do was include the definition of boo in foo.cpp
    Code:
    //FILE - foo.cpp
    #include "foo.h"
    
    // IMPORTANT: needed to actually use/create boo!
    #include "boo.h"
    
    foo::foo() { }
    boo* foo::getBoo() { return new boo(); }
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  9. #9
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by ChaosEngine
    eh? why are you including foo.h and forward declaring class foo?
    if you include foo.h in an implementation-file first thing that happens in foo.h is to include boo.h and then when the compiler sees
    Code:
        foo* getFoo();
    -> error (because it has not seen the dclaration of foo yet ).

    Quote Originally Posted by ChaosEngine
    Actually the OP was really close at the beginning! all you needed to do was include the definition of boo in foo.cpp
    There would already have been an error before the compiler sees the include boo.h in foo.cpp

    Kurt
    Last edited by ZuK; 12-11-2005 at 03:54 PM.

  10. #10
    semi-colon generator ChaosEngine's Avatar
    Join Date
    Sep 2005
    Location
    Chch, NZ
    Posts
    597
    Quote Originally Posted by ZuK
    if you include foo.h in an implementation-file first thing that happens in foo.h is to include boo.h and then when the compiler sees

    There would already have been an error before the compiler sees the include boo.h in foo.cpp

    look at your own post
    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    #include "foo.h"
    class foo;
    class boo
    {
      public:
        boo();
        foo* getFoo();
    };
    #endif
    you obviously didn't read my post properly. you are including foo.h and then forward declaring (more like reverse declaring) class foo!!

    your code expands to
    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    
    //#include "foo.h" expands to
    class boo;
    class foo
    {
      public:
        foo();
        boo* getBoo();
    };
    
    // no we have a pointless forward declare. 
    class foo;
    class boo
    {
      public:
        boo();
        foo* getFoo();
    };
    #endif
    Quote Originally Posted by ZuK
    Code:
        foo* getFoo();
    -> error (because it has not seen the dclaration of foo yet ).
    yes it has. look at the OP's code
    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    
    // chaosengine - this includes foo declaration
    #include "foo.h" 
    
    class boo
    {
      public:
        boo();
        foo* getFoo();
    };
    #endif
    Once again the only error is that foo.cpp has not seen the boo declation which it needs to create a new boo. including boo.h fixes this.
    "I saw a sign that said 'Drink Canada Dry', so I started"
    -- Brendan Behan

    Free Compiler: Visual C++ 2005 Express
    If you program in C++, you need Boost. You should also know how to use the Standard Library (STL). Want to make games? After reading this, I don't like WxWidgets anymore. Want to add some scripting to your App?

  11. #11
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    @ChaosEngine: First of all I have to agree that your solution is the the easiest ( maybe best ) solution for the original problem.
    Now I want to make my point clear so that I do not look like a complete idiot.
    I did not read the OP's code very well. I just saw that he included only the corresponding header in his implementation files and then I looked at boo.h and saw that he included "foo.h" at the top. Thought "foo.h" was including "boo.h" as well ( now I know he did'nt ).

    In header files I usually try to include all the depending headers so that I need to include only the corresponding header in my implementation files ( and any other headers not referenced in the header ).
    But that leads to a problem if there are cyclic dependecies like in this case
    example:
    Code:
    //FILE - boo.h
    #ifndef BOO_H
    #define BOO_H
    // I agree that looks stupid at first
    // include the header "foo.h" and forward declare class foo
    // trouble is "foo.h" may or may not get included at this point
    // think what happens if this file was actually included from the top of
    // "foo.h" ( in this case class foo would not yet have bee declared )
    // and the following line would get blocked by the include-guards in "foo.h"
    #include "foo.h"
    class foo;        // without forward foo would still be unknown
    class boo
    {
      public:
        boo();
        foo* getFoo();   // error without forward declaration
    };
    #endif
    When "boo.h" is included e.g from boo.cpp then the forward declaration is useless ( but allowed ). But we would have the same problem with the include-guards in foo.h.

    Hope I could clarify my point

    Kurt

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If a forward declaration is sufficient, then you should just use the forward declaration. If the full class definition is required, then you include the header with the class definition. Therefore, you should never have a reason to put in both. In this example, there is no need to #include "Foo.h" inside Boo.h because a forward declaration is sufficient.

    IMO, the best solution is to use a forward declaration only in both Foo.h and Boo.h, and then #include both "Foo.h" and "Boo.h" in both cpp files.

  13. #13
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    I still prefer the common header file:
    common.h
    Code:
    #ifndef COMMON_H_
    #define COMMON_H_
    class foo;
    class bar;
    #endif
    foo.h
    Code:
    #ifndef FOO_H_
    #define FOO_H_
    #include "common.h"
    
    class foo
    {
            bar* bptr;
            int x;
            public:
                    foo(bar* b=0, int y=0);
                    void setX(int);
                    int getX();
                    void setB(bar*);
                    bar* getB();
    };
    #endif
    bar.h
    Code:
    #ifndef BAR_H_
    #define BAR_H_
    #include "common.h"
    
    class bar
    {
            foo* fptr;
            int z;
            public:
                    bar(foo* f=0, int y=0);
                    void setZ(int);
                    int getZ();
                    void setF(foo*);
                    foo* getF();
    };
    #endif
    foo.cpp
    Code:
    #include "foo.h"
    
    foo::foo(bar* b, int y) : bptr(b), x(y) {}
    
    void foo::setX(int y) { x = y; }
    int foo::getX() { return x; }
    
    void foo::setB(bar *b) { bptr=b; }
    bar* foo::getB() { return bptr; }
    bar.cpp
    Code:
    #include "bar.h"
    
    bar::bar(foo* f, int y) : fptr(f), z(y) {}
    
    void bar::setZ(int y) { z = y; }
    int bar::getZ() { return z; }
    
    void bar::setF(foo *f) { fptr=f; }
    foo* bar::getF() { return fptr; }
    main.cpp
    Code:
    #include <iostream>
    #include "foo.h"
    #include "bar.h"
    
    using namespace std;
    
    int main()
    {
            foo Foo(0, 10);
            bar Bar(0, 100);
            Foo.setB(&Bar);
            Bar.setF(&Foo);
    
            cout<<"Foo.getX() = "<<(Foo.getX())<<endl
                <<"Bar.getZ() = "<<(Bar.getZ())<<endl
                <<"Foo.getB()->getZ() = "<<(Foo.getB()->getZ())<<endl
                <<"Bar.getF()->getX() = "<<(Bar.getF()->getX())<<endl;
    }

  14. #14
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    That seems like a waste of a header file. Especially in this case when you are creating an entirely new header file to replace a single forward declaration in two other headers.

    BTW, based on the original example, you'd also have to #include "foo.h" in bar.cpp and #include "bar.h" in foo.cpp.

  15. #15
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Thantos:
    Yes your example works fine until you add somesthing like this:
    Code:
    #include "foo.h"
    
    foo::foo(bar* b, int y) : bptr(b), x(y) {}
    
    void foo::setX(int y) { x = y; }
    int foo::getX() { return x; }
    
    void foo::setB(bar *b) { bptr=b; }
    bar* foo::getB() { return bptr; }
    
    void foo::initBar() { bptr = new bar(); }
    // now you would be forced to #include "bar.h" 
    Guess there is no "perfect solution"
    Kurt

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can you Initialize all classes once with New?
    By peacerosetx in forum C++ Programming
    Replies: 12
    Last Post: 07-02-2008, 10:47 AM
  2. Multiple Inheritance - Size of Classes?
    By Zeusbwr in forum C++ Programming
    Replies: 10
    Last Post: 11-26-2004, 09:04 AM
  3. im extreamly new help
    By rigo305 in forum C++ Programming
    Replies: 27
    Last Post: 04-23-2004, 11:22 PM
  4. Exporting VC++ classes for use with VB
    By Helix in forum Windows Programming
    Replies: 2
    Last Post: 12-29-2003, 05:38 PM
  5. Prime Number Generator... Help !?!!
    By Halo in forum C++ Programming
    Replies: 9
    Last Post: 10-20-2003, 07:26 PM