Diogenes Creosote
Diogenes Creosote

Reputation: 1942

mutually referential classes yield "incomplete type" error

I have a situation in which A has a reference to a class C defined inside B, and C has an instance of class B.

When I try to compile the code below, I get "field a has incomplete type". I assume this is because the compiler does not know how much memory it should allocate for an instance of A.

class A;

class B {
public:
  class C {
    A a;
  };
};

class A {
  A(const B::C& _c) 
    : c(_c)
  {}
  const B::C& c;
};

But when I try to compile this, I get "C in class B does not name a type":

class B;
class B::C;

class A {
  A(const B::C& _c) 
    : c(_c)
  {}
  const B::C& c;
};


class B {      
public:
  class C {
    A a;
  };
};

How can I convince the compiler that B::C is a real type?

Upvotes: 3

Views: 307

Answers (2)

j_random_hacker
j_random_hacker

Reputation: 51246

As an absolute guess, I notice there's one permutation you haven't tried:

class B {
public:
  class C; // Forward declaration
};

class A {
  A(const B::C& _c) 
    : c(_c)
  {}
  const B::C& c;
};

class B::C {
  A a;
  C() : a(*this) {}    // Thanks Nim for pointing this out!
};

This is quite possibly illegal, but worth a shot I think. If it doesn't work, then I don't see any way around the problem.

Upvotes: 5

UncleBens
UncleBens

Reputation: 41351

The forward declaration for A doesn't serve a purpose: you can't declare an instance of an incomplete type.

As to B::C, I don't think you can use nested names in an incomplete type. Just don't nest C in B: as far as I know this doesn't give you any significant advantages* and stops you from forward declaring it.

*The only advantage I can think of is that you can define it in the private section, but then A would have no business with it in the first place.

Upvotes: 2

Related Questions