tags:

views:

1360

answers:

5

Is there anyway to declare an object of a class before the class is created in C++? I ask because I am trying to use two classes, the first needs to have an instance of the second class within it, but the second class also contains an instance of the first class. I realize that you may think I might get into an infinite loop, but I actually need to create and instance of the second class before the first class.

+4  A: 

You can't declare an instance of an undefined class but you can declare a pointer to one:

class A;  // Declare that we have a class A without defining it yet.

class B
{
public:
    A *itemA;
};

class A
{
public:
    B *itemB;
};
Adam Pierce
...or a reference to one: MyClass
Pat Notz
A: 

Is this close to what you want: The first class contains the second class, but the second class (that is to be created first) just has a reference to the first class?

Chris Jester-Young
I am actually trying to do the reverse, where the first class references the second class and the second class contains an instances of the first class.
Matt Pascoe
+31  A: 

You can't do something like this:

class A {
    B b;
};
class B {
    A a;
};

The most obvious problem is the compiler doesn't know how to large it needs to make class A, because the size of B depends on the size of A!

You can, however, do this:

class B; // this is a "forward declaration"
class A {
    B *b;
};
class B {
    A a;
};

Declaring class B as a forward declaration allows you to use pointers (and references) to that class without yet having the whole class definition.

Greg Hewgill
A: 

This is called cross reference. See here an example.

Iulian Şerbănoiu
+2  A: 

There's an elegant solution using templates.

template< int T > class BaseTemplate {};
typedef BaseTemplate< 0 > A;
typedef BaseTemplate< 1 > B;
// A
template<> class BaseTemplate< 0 >
{
public:
   BaseTemplate() {} // A constructor
   B getB();
}

// B
template<> class BaseTemplate< 1 >
{
public:
   BaseTemplate() {} // B constructor
   A getA();
}

inline B A::getB() { return A(); }
inline A B::getA() { return B(); }

This code will work! So, why does it work? The reason has to do with how templates are compiled. Templates delay the creation of function signatures until you actually use the template somewhere. This means that neither getA() nor getB() will have their signatures analyzed until after both classes A and B have already been fully declared. That's the magic of this method.

tfinniga
Interesting (although it contains several typos). But the 'getA' and 'getB' are really factories: they return new instances (by value). An instance of A does not have-a B nor does an instance of B have-an A.
jwfearn