Когда компилятор компилирует класс User
и переходит к MyMessageBox
строке, MyMessageBox
еще не определено. Компилятор понятия не имеет, что MyMessageBox
существует, поэтому не может понять значение вашего члена класса.
Вы должны убедиться, что MyMessageBox
он определен, прежде чем использовать его в качестве члена. Это решается изменением порядка определения на обратный. Однако у вас циклическая зависимость: если вы переместитесь MyMessageBox
выше User
, то в определении MyMessageBox
имя User
не определится!
Что вы можете сделать, так это объявить вперед User
; то есть объявлять, но не определять. Во время компиляции тип, который объявлен, но не определен, называется неполным типом . Рассмотрим более простой пример:
struct foo; // foo is *declared* to be a struct, but that struct is not yet defined
struct bar
{
// this is okay, it's just a pointer;
// we can point to something without knowing how that something is defined
foo* fp;
// likewise, we can form a reference to it
void some_func(foo& fr);
// but this would be an error, as before, because it requires a definition
/* foo fooMember; */
};
struct foo // okay, now define foo!
{
int fooInt;
double fooDouble;
};
void bar::some_func(foo& fr)
{
// now that foo is defined, we can read that reference:
fr.fooInt = 111605;
fr.foDouble = 123.456;
}
По вперед объявляя User
, MyMessageBox
все еще может сформировать указатель или ссылку на него:
class User; // let the compiler know such a class will be defined
class MyMessageBox
{
public:
// this is ok, no definitions needed yet for User (or Message)
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message>* dataMessageList;
};
class User
{
public:
// also ok, since it's now defined
MyMessageBox dataMsgBox;
};
Вы не можете сделать это наоборот: как уже упоминалось, член класса должен иметь определение. (Причина в том, что компилятор должен знать, сколько памяти User
занимает, и знать, что ему нужно знать размер своих членов.) Если бы вы сказали:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
Это не сработает, так как он еще не знает размера.
Кстати, эта функция:
void sendMessage(Message *msg, User *recvr);
Наверное, не стоит брать ни одного из них по указателю. Вы не можете отправить сообщение без сообщения, а также вы не можете отправить сообщение без пользователя, которому его отправили. И обе эти ситуации можно выразить, передав null в качестве аргумента для любого параметра (null - это совершенно допустимое значение указателя!)
Скорее используйте ссылку (возможно, const):
void sendMessage(const Message& msg, User& recvr);