Thread: circular header dependencies

  1. #1
    Registered User
    Join Date
    Mar 2016
    Posts
    13

    circular header dependencies

    Here is a problem of circular dependency. I want to allow a class B ctor friend access to private members of a class A object. But in order to tell class A this, class A needs to know about the existence of the class B::B(const A&) ctor, so a simple forward declaration will not work.
    Code:
    //A.h:
    #ifndef A_H
    #define A_H
    #include "B.h"
    
    class A {
    public:
        A(int i);
        friend B::B(const A &);
    private:
        int _i;
    };
    
    #endif
    
    //B.h:
    #ifndef B_H
    #define B_H
    #include "A.h"
    
    class B {
    public:
        B(const A &);
    private:
        int deg;
    };
    
    #endif
    
    //A.cpp:
    #include "A.h"
    A::A(int i) : _i(i) { }
    
    //B.cpp:
    #include "B.h"
    B::B(const A &a) : deg(a._i) { }
    My basic approach was to have each class header include the other class header so that they each know of the other's entire structure. But inevitably one header comes before the other (of course) so it seems that it is simply impossible to have each class know of the other classes' complete definition as it is being compiled.

    So there is no main() here. Errors are displayed with just:
    Code:
    gcc B.cpp

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Instead of including the header for class A in the header for class B, forward declare class A in the header for class B, just before the definition of class B.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    What's wrong with A having a public accessor function, instead of messy friendship of your private parts?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Mar 2016
    Posts
    13
    Quote Originally Posted by laserlight View Post
    Instead of including the header for class A in the header for class B, forward declare class A in the header for class B, just before the definition of class B.
    Yes, that exposes the name A so that the B(const A &) ctor can be declared. I actually came across that solution after I posted my question.

    Then, in order to compile B.cpp, one must still #include "A.h" either in B.h after class B definition, or in B.cpp before the definition of B::B(const A &a) ctor, so that a._i is known of. (actually, B.cpp could just #include "A.h" as that #includes "B.h", but i just let the hdr guards do their thing.)

  5. #5
    Registered User
    Join Date
    Mar 2016
    Posts
    13
    Quote Originally Posted by Salem View Post
    What's wrong with A having a public accessor function, instead of messy friendship of your private parts?
    Yes, that is a better solution, e.g, define a public:
    Code:
    int get_deg() const { return _i; }
    method for class A. At this point, I'm just using this code to study about dependencies in class definitions. The real code, from which I distilled this example, was corrected as you suggest.
    Last edited by dslowik; 05-31-2017 at 03:57 PM. Reason: made method get_deg const.

  6. #6
    Registered User
    Join Date
    Mar 2016
    Posts
    13
    Quote Originally Posted by Salem View Post
    messy friendship of your private parts
    Actually, it would be easier to allow the even messier friendship of declaring the entire class B to be a friend of class A. That would only require a forward declaration of class B prior to the class A definition, which would then include the statement: friend class B; (but still require a complete definition of class A prior to referring to members of A in B.cpp implementation.)

    By restricting only a particular method or ctor of B as friend of A, as I did, the complete class definition of B must be available at the point of class A definition. Thus began the dance of headers. [you, in particular, probably already know this, just being explicit since that's generally a good thing ]
    Last edited by dslowik; 05-31-2017 at 04:36 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A size based variable header w/o dependencies.
    By User Name: in forum C Programming
    Replies: 8
    Last Post: 07-18-2010, 08:40 PM
  2. C app with all dependencies
    By bradleyd in forum C Programming
    Replies: 4
    Last Post: 05-19-2007, 11:47 PM
  3. circular dependencies, forward doesn't help
    By pheres in forum C++ Programming
    Replies: 14
    Last Post: 11-24-2006, 04:15 PM
  4. Dependencies
    By spank in forum Windows Programming
    Replies: 4
    Last Post: 08-14-2006, 03:51 AM
  5. Circular doubly linked list with dummy header
    By mag_chan in forum C Programming
    Replies: 5
    Last Post: 10-31-2005, 08:44 AM

Tags for this Thread