circular reference in parent/child classes

I have been trying to understand some code that another guy wrote,
and though his code compiles and runs, it seems like it should
never have compiled.

He has 2 classes. One class is basically the parent, and it
includes a pointer to the child it creates. As the child is being
created, the parent passes the constructor a "this" pointer, so
the child can later access variables in the parent.

When I try to duplicate this logic, with a parent class called
alpha and a child class called bravo, my compiler (Visual C++.net)
complains thusly:

------ Build started: Project: main, Configuration: Debug Win32 -
Compiling...
bravo.cpp
\visual_cpp\solutions\test\main\bravo.h(8) : error C2460:
'bravo::alpha' : uses 'bravo', which is being defined

I believe my compiler is complaining about the "circular"
reference of alpha referencing bravo, and vice versa. Frankly, the
compiler error makes sence to me. What does not make sence is how
this other guy did the same sort of thing and got away with it.

Any ideas

I'm reluctant to post the other guy's code, since there is so much
of it, but I'll include my little test program below...

============ main.cpp ===========

#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}

============ alpha.h ============

class alpha
{
public:
    int a;
    bravo *my_child;
    alpha();
};

============ alpha.cpp ===========

#include "stdafx.h"
#include "alpha.h"
#include "bravo.h"

alpha::alpha()
{
    bravo *my_child = new bravo(this);
    a = 0;
}

============ bravo.h =============

class bravo
{
public:
    int b;
    alpha *my_parent;
    bravo(alpha *);
};

============ bravo.cpp ===========

#include "stdafx.h"
#include "bravo.h"
#include "alpha.h"

bravo::bravo(alpha* a_ptr)
{
    my_parent = a_ptr;
    b = 0;
}



Answer this question

circular reference in parent/child classes

  • David Seymour

    I didn't believe it until I tried it, but you are absolutely correct. Tell your boss that I said it was okay for you to take the rest of the day off. Here is the code which compiles just fine::

    ============== main.cpp ===============

    #include "stdafx.h"
    #include "bravo.h"
    #include "alpha.h"

    int _tmain(int argc, _TCHAR* argv[])
    {
    alpha aaa;
    return 0;
    }

    =============== alpha.h ================

    class alpha
    {
    public:
    int a;
    bravo *my_child; // variable
    alpha(); // constructor
    };

    =============== alpha.cpp ==============

    #include "stdafx.h"
    #include "bravo.h"
    #include "alpha.h"

    alpha::alpha()
    {
    // bravo.h needed because of call to "new"
    bravo *my_child = new bravo(this);
    a = 0;
    }

    =============== bravo.h =================

    class alpha;

    class bravo
    {
    public:
    int b;
    alpha *my_parent; // variable
    bravo(alpha *); // constructor
    };

    =============== bravo.cpp ===============

    #include "stdafx.h"
    #include "bravo.h"

    bravo::bravo(alpha* a_ptr)
    {
    my_parent = a_ptr;
    b = 0;
    }


  • Moses Bunting

    Hi Harold. I think I have the solution (or at least "a solution").

    My first problem was that I was not using "incomplete class declarations". Amazing stuff, that.

    My second problem was that I was expecting too much from the "incomplete class declaration". Apparently, the "incomplete class declaration" will allow you to declare pointers to the incomplete class (the compiler knows exactly how many bytes are in a pointer). But, you can not declare an instance of the incomplete class, since there is not enough info in the "incomplete class declaration" for the compiler to know (as of yet) how many bytes the class will require.

    I'll include the final code that compiles.

    ============== main.cpp ===============

    // main.cpp : Defines the entry point for the console application.
    //

    #include "stdafx.h"
    #include "alpha.h"
    #include "bravo.h"

    int _tmain(int argc, _TCHAR* argv[])
    {

    alpha a;
    bravo b(&a);
    a.my_child = &b;
    return 0;
    }

    =============== alpha.h ================

    class bravo; // incomplete class declaration

    class alpha
    {
    public:
    int a;
    bravo *my_child;
    alpha();
    };

    =============== alpha.cpp ==============

    #include "stdafx.h"
    #include "alpha.h"

    alpha::alpha()
    {
    my_child = NULL;
    a = 0;
    }

    =============== bravo.h =================

    class alpha; // incomplete class declaration

    class bravo
    {
    public:
    int b;
    alpha *my_parent;
    bravo(alpha *);
    };

    =============== bravo.cpp ===============

    #include "stdafx.h"
    #include "bravo.h"

    bravo::bravo(alpha* a_ptr)
    {
    my_parent = a_ptr;
    b = 0;
    }



  • TGhostH

    Try placing a default constructor (one with no parameters) in the bravo class.

  • Mark TK

    You don't have to move a part of your code to the main() funtion to avoid this error -
    'bravo' : class has no constructors
    All you need to do is to include bravo.h in alpha.cpp. You need complete definition of brave class to create its instance (line 6 in alpha.cpp)

  • LiquidLithium

    Hi Harold. I think you solved most of the problem with your suggestion. I was not familiar with the technique of "incomplete class declarations". Most of the errors went away. bravo.cpp compiled fine, but alpha.cpp got this error:

    Compiling...
    bravo.cpp
    alpha.cpp
    Projects\test\main\alpha.cpp(6) : error C2514: 'bravo' : class has no constructors
    Projects\test\main\alpha.h(1) : see declaration of 'bravo'

    I don't really understand what this is trying to tell me. The bravo class most certainly does have one (and only one) constructor. I'll include an updated version of the alpha and bravo files below. Thanks very much for your help.

    ============ main.cpp ===========

    #include "stdafx.h"
    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }

    ============ alpha.h ============

    class bravo;

    class alpha
    {
    public:
    int a;
    bravo *my_child;
    alpha();
    };

    ============ alpha.cpp ===========

    #include "stdafx.h"
    #include "alpha.h"

    alpha::alpha()
    {
    bravo *my_child = new bravo(this);
    a = 0;
    }

    ============ bravo.h =============

    class alpha;

    class bravo
    {
    public:
    int b;
    alpha *my_parent;
    bravo(alpha *);
    };

    ============ bravo.cpp ===========

    #include "stdafx.h"
    #include "bravo.h"

    bravo::bravo(alpha* a_ptr)
    {
    my_parent = a_ptr;
    b = 0;
    }



  • Susan2

    Hi,

    Just place the following at the top of every header file

    class bravo; (in the alpha header file)

    class alpha; (in the bravo header file)

    also remove the cross include calls for alpha.h and bravo.h

    It should compile!



  • circular reference in parent/child classes