Circular inclusion problem (forward declare)

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • philuu12
    New Member
    • Oct 2011
    • 14

    Circular inclusion problem (forward declare)

    Hi,

    I got the following circular inclusion problem, and hope that
    someone could show me some help here.

    Code:
    =============== ===
    Code:
         1  #include <iostream>
         2  #include <string>
         3  using namespace std;
         4
         5  // class Welcome;
         6  class Mediator;
         7
         8  class Welcome
         9  {
        10     public:
        11          Welcome(Mediator* m)
        12          {  mediator = m;  }
        13
        14          void go()
        15          {  mediator->handle("Welcome !!");  }
        16
        17     private:
        18          Mediator*       mediator;
        19
        20
        21  };
        22  class Mediator
        23  {
        24     public:
        25          Mediator()
        26          {  welcome = new Welcome(this);  }
        27
        28          void handle(string state)
        29          {  cout << state << endl;  }
        30
        31          Welcome* getWelcome()
        32          {  return welcome; }
        33
        34     private:
        35          Welcome*        welcome;
        36
        37  };
        38
        39  int main()
        40  {
        41     Mediator* mediator = new Mediator();
        42
        43     mediator->getWelcome()->go();
        44
        45     delete mediator;
        46  }
    The compile errors below:
    224 unix-machine[**]:/class/PATTERN-DESIGN/mediator% g++ webpage1.cc
    webpage1.cc: In member function 'void Welcome::go()':
    webpage1.cc:15: error: invalid use of undefined type 'struct Mediator'
    webpage1.cc:6: error: forward declaration of 'struct Mediator'
    *************** *************** ************

    I understand the forward declaring will not allow me to call the member function on line 15, how do I go about resolving this on line 15? I tried to swap the placement of 2 classes, but no avail.

    thanks,

    Tera
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    To resolve a circular dependence problem you are on the right track. However you need to be aware of what a forward declaration does. It informs the compiler that a structure or class with the given name exists and this allows the compiler to create pointers or references to that class. What it does not do is allow the compiler to access any members of the class or anything to do with the classes structure (for example its size through the sizeof operator).

    So you have a problem in Welcome::go because you try to access the Mediator::handl e member that the compiler knows nothing about.

    Your mistake is to combine the declaration of the class and its methods and definition of those methods. While that works for normal classes for classes in a circular dependency it doesn't for the very reason that your code doesn't; in the method definitions you do not have all the declarations you need to compile them. You need to declare everything first and only then define the methods.

    If you split you classes so that they are each in a header and a cpp file then you can use forward declaration to allow you to declare the 2 classes successfully and having done that you can then define their methods without trouble in the presence of the full definition of both classes.

    So for example you Welcome class would become (you would need to do this for mediator as well)

    Code:
    // Welcome Header
    class Mediator;
    
    class Welcome
    {
    public:
      Welcome(Mediator* m);
    
    private:
      Mediator*       mediator;
    };
    Code:
    #include "welcome.h"
    #include "mediator.h"
    
    Welcome::Welcome(Mediator* m)
    {
      mediator = m;
    }
    
    void Welcome::go()
    {
      mediator->handle("Welcome !!");
    }
    Note that in this code the Welcome header only uses a pointer to Mediator so a forward declaration works. In the code file by the time the members of Mediator are used in Welcome::go the Mediator class has been declared in its header so the compiler wont have a problem.

    Comment

    • philuu12
      New Member
      • Oct 2011
      • 14

      #3
      Hi, Banfa:

      Thanks for the response.

      Wonder if there is a way to resolve this circular dependency problem with simply one file (ie, no header and implementation files separately), with all the methods being in-lined in header file?

      Thx,

      TR

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        You could do your file would have to have this layout

        Code:
        // Declaration of first class
        
        // Declaration of second class
        
        // Definition of methods of first and second class
        It would be quite messy in my opinion.

        Comment

        Working...