Forward declaration of class doesn't seem to work in C++

Lopper picture Lopper · Dec 11, 2009 · Viewed 13.7k times · Source

The follwing code is compiled in VC++6. I don't understand why I am getting the compilation error C2079: 'b' uses undefined class 'B' for the following code.

Class B Source

#include "B.h"

void B::SomeFunction()
{
}

Class B Header

#include "A.h"

struct A;

class B
{
    public:
        A a;
        void SomeFunction();
};

struct A Header

#include "B.h"

class B;

struct A
{
    B b;
};

If I changed class B header to the following, then there will be no error. But the header declaration won't be at the top!

Class B Header with weird header declaration

struct A;

class B
{
     public:
        A a;
        void SomeFunction();
};

#include "A.h"

Answer

Matt Davis picture Matt Davis · Dec 11, 2009

In order to define a class or struct, the compiler has to know how big each member variable of the class is. A forward declaration does not do this. I've only ever seen it used for pointers and (less often) references.

Beyond that, what you're trying to do here cannot be done. You cannot have a class A that contains an object of another class B that contains an object of class A. You can, however, have class A contain a pointer to class B that contains an object of class A.

B.cpp

#include "B.h"

void B::SomeFunction()
{
}

B.h

#ifndef __B_h__  // idempotence - keep header from being included multiple times
#define __B_h__
#include "A.h"

class B
{
public:
    A a;
    void SomeFunction();
};

#endif // __B_h__

A.h

#ifndef __A_h__  // idempotence - keep header from being included multiple times
#define __A_h__
#include "B.h"

class B; // forward declaration

struct A
{
    B *b;  // use a pointer here, not an object
};

#endif // __A_h__

Two points. First, be sure to use some form of idempotence to keep the headers from being included multiple times per compilation unit. Second, understand that in C++, the only difference between classes and structs is the default visibility level - classes use private visibility by default while structs use public visibility by default. The following definitions are functionally equivalent in C++.

class MyClass
{
public: // classes use private visibility by default
    int i;
    MyClass() : i(13) { }
};

struct MyStruct
{
    int i;
    MyStruct() : i(13) { }
};