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;
}

circular reference in parent/child classes
David Seymour
============== 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
Mark TK
'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!