1

Am I missing something here?

class Foo;

class Bar {
    public:
        Foo foo;
};

class Foo { };

Error:

error C2079: 'Bar::foo' uses undefined class 'Foo'

Vishal Suthar
  • 17,013
  • 3
  • 59
  • 105
Dissident Rage
  • 2,610
  • 1
  • 27
  • 33
  • 3
    You should use pointer Foo * foo, coz before Foo is defined, the compiler does not know the size of Foo, thus can not decide the size of Bar. – Min Lin Feb 28 '13 at 08:17
  • 1
    "...uses incomplete type 'Foo'" would be a clearer error message. – Nemo Feb 28 '13 at 08:18
  • Foo is undefined *at the time that* `Bar` is defined. The compiler needs to be able to determine how much memory space a `Bar` will take up, and it doesn't yet know how big a `Foo` is. – Peter Wood Feb 28 '13 at 08:19
  • 2
    An explanation of what you can and cannot do with incomplete types: http://stackoverflow.com/a/553869/20984 – Luc Touraille Feb 28 '13 at 08:19
  • So codependent classes with circular methods are impossible? – Dissident Rage Feb 28 '13 at 08:30
  • Normally you use a pointer (or smartpointer) to get around this limitation. I have done this 1000s of times over the years. – drescherjm Feb 28 '13 at 08:34
  • 1
    It depends on what you call "codependent classes with circular methods". Basically, the only thing you cannot do is have a class `A` with a member of type `B`, that itself has a member of type `A` (this seems sensible, as that would be an infinite data structure). Everything else is possible, as long as you separate declaration from definition (i.e., as long as you use implementation files). – Luc Touraille Feb 28 '13 at 08:48
  • Alright. Thank you all for the help. – Dissident Rage Feb 28 '13 at 15:42

2 Answers2

8

When you forward-declare a class, you can make pointers and references to it, but you cannot make members of the type of forward-declared class: the full definition of Foo is needed to decide the layout of the outer class (i.e. Bar), otherwise the compiler cannot make a decision on the size and the structure of Bar.

This is allowed, though:

class Foo;

class Bar {
    public:
        Foo* fooPtr;
        Foo& fooRef;
};

The reason the pointers and references to forward-declared classes are allowed is that the sizes of pointers and references do not depend on the structure of the class to which they point (or which they reference).

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Yes you are missing something important: A question.

I assume you want to know what's wrong in the code, and why the compiler issues an error.

The compiler has to know the size of Foo in order to calculate the layout of the class Bar. The size of Foo objects is determined by their layout, to know that layout, the compiler has to know the class definition. At the point where you declare the Member variable foo, it merely knows that Foo exists, but not its size, because you have given it only a declaration, not a definition before.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90