2

So lets say that I have a class named A. Class A has several basic properties, however one of it's properties is supposed to be of type Class A. Here is an example of what I am talking about:

class A {
public:
    int a;
    bool b;
    A c;
};

However, when I try to build this, I get the error "incomplete type is not allowed", which I am assuming has to do with the fact that property c does not have a definition for A yet, but even if I put:

class A;

before I construct class A, however I still get the error "incomplete type is not allowed". If anyone knows how to create a property of type class A inside of class A, I would appreciate your help. Thanks

Edit: I do not believe this post is a duplicate because I am trying to find out How you can create a property of type class A inside class A, instead of simply "why you can't create an instance of itself..."

mike bayko
  • 375
  • 5
  • 20
  • 4
    Think about it, if A contains A, then that instance of A constains A which also contains and instance of A.... What would the size of that be? Or alternatively, when would construction of such an object end? – Borgleader Jul 04 '17 at 20:08
  • You can make `c` a `A*`. – Jesper Juhl Jul 04 '17 at 20:09
  • 2
    You may be thinking of other languages where declaring a member of type `A` really just declares a reference. That's not how C++ works. If you want to declare a pointer, or a reference, or some variety of smart pointer, you do that explicitly. Otherwise, you're saying every `A` has to contain another `A`, infinitely. – user2357112 Jul 04 '17 at 20:09
  • 1
    This would lead to an [ouroboros data structure](https://en.wikipedia.org/wiki/Ouroboros). What about a pointer or a reference? – tadman Jul 04 '17 at 20:09
  • You can make `c` a pointer and dynamically allocate it, e. g. `std::unique_ptr c;` which essentially creates a forward list. – zett42 Jul 04 '17 at 20:11
  • Other possible dupe target: https://stackoverflow.com/q/2706129/1896169 – Justin Jul 05 '17 at 00:19

2 Answers2

3

Yeah this is not possible, you have to declare it as a pointer like so:

class A {
public:
   int a;
   bool b;
   A* c;
};

Then you can just allocate c on the heap. The reason is that the compiler cannot know the size of A. Think like a compiler. Could you figure out the size of A? Well maybe 4 bytes for member a. Then maybe a byte for b. And for c, we have to look inside the class definition of A. Well the size of A is therefore 4 bytes for member... You see where this is going to?

DaOnlyOwner
  • 343
  • 3
  • 8
  • Thank you, I see the issue with what I was trying to do now. Also what if later i made two instances of class A, A1, and A2, and I wanted A1's c to point to A2, and A2's c to point to A1, would this be doable? – mike bayko Jul 04 '17 at 20:48
  • Yes, certainly! You can create both instances first and then change their `c` to point to each other. – DaOnlyOwner Jul 04 '17 at 23:07
  • Thank you, this helps a lot! – mike bayko Jul 04 '17 at 23:09
1

As far as I know you need complete types to define data members by value because they are allocated directly within each class object and this is important to know the class object size. The forward declaration doesn't help here because it only provides an incomplete type. You can have a reference or pointer to A, for example:

class A {
public:
    int a;
    bool b;
    A* c;
};
Cosme
  • 191
  • 2
  • 6