field has incomplete type

May 30, 2012 at 12:19am
Hello,

I believe that I have some sort of circular inclusion error in my code, and the error I am getting is:

field 'm_advArray1' has incomplete type


This is my code. As you can see, I try to compose my MainClass of another class PieceClass1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#ifndef COMPOSITIONCLASSES_H
#define COMPOSITIONCLASSES_H

#include <iostream>
using namespace std;

class PieceClass1;

class MainClass
{
private:
    int m_value1;
    const int m_value2;
    int* m_nPntr1;
    PieceClass1 m_advArray1;
public:
    MainClass(int arg_m_value);
    ~MainClass();
};

MainClass::MainClass(int arg_m_value = 0): m_value1(arg_m_value), m_value2(arg_m_value), m_nPntr1(0)
{
}

MainClass::~MainClass()
{
    delete m_nPntr1;
}
/////////////////////////////////////////////////////
class PieceClass1
{
private:
    int array1[5];
public:
    PieceClass1(int startingValue = 0);
    friend ostream& operator<<(ostream&, const PieceClass1&);
};

PieceClass1::PieceClass1(int startingValue)
{
    for (int i = 0; i < 5; ++i)
    {
        array1[i] = startingValue;
    }
}

ostream& PieceClass1::operator<<(ostream& output, const PieceClass1& inputClass)
{
    for (int i = 0; i < 5; ++i)
    {
        output << inputClass.array1[i] << "\n";
    }

}

#endif // COMPOSITIONCLASSES_H 


Thanks,
Flurite
Last edited on May 30, 2012 at 12:20am
May 30, 2012 at 12:29am
In order to create a class instance like that, the compiler needs the full definition of the class so it knows how large it needs to be.

Move the definition to where you have the declaration and it should work.
May 30, 2012 at 12:39am
@firedraco,

That would work if only one incorporated the other, which is what I am doing in that case. But how would I do it if both incorporated each other?
May 30, 2012 at 2:04am
They can't.
This box has our universe inside it

There is no 1 to 1 relationship. They would be the same thing in that case.
However, you could maintain a reference only needing a forward declaration.
May 30, 2012 at 10:52am
@ne555,

Ahh, I see. Just out of curiosity, why would references be a safe way to kind of "bypass" a class prototype?
May 30, 2012 at 8:07pm
Any ideas?
May 30, 2012 at 9:02pm
The compiler doesn't need to know the size of the class to make a reference to it.
May 30, 2012 at 10:15pm
Why does the size of the class matter?
May 30, 2012 at 10:38pm
Because a class, among other things, contains all the data inside of itself. So when you say it contains a PieceClass1, the compiler needs to put an entire PieceClass1 inside there, which it can't do if it doesn't have the definition. If you use a reference, it only needs to store a reference, which is independent of the class definition itself.
May 30, 2012 at 11:00pm
@Zhuge,

Okay, I see. The compiler only checks whether the data type its referencing to exists. Otherwise, it does not check anything else.

Thanks everyone for the help so far!

However, there is no way to initialize it, besides using pointers. I guess one-way composition is the only way to go.
Last edited on May 30, 2012 at 11:23pm
May 31, 2012 at 12:12am
Using pointers isn't so bad. It has all kinds of advantages, from late binding of that member to reducing the size of header files.

It's easy to forget how bloated C++ header can become until you go back and compile a C program on the same kit. 10 times faster compilation is not uncommon.
Last edited on May 31, 2012 at 12:14am
Topic archived. No new replies allowed.