field has incomplete type

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
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.
@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?
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.
@ne555,

Ahh, I see. Just out of curiosity, why would references be a safe way to kind of "bypass" a class prototype?
Any ideas?
The compiler doesn't need to know the size of the class to make a reference to it.
Why does the size of the class matter?
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.
@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
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
Topic archived. No new replies allowed.