Ответ 1
Когда компилятор компилирует класс User
и попадает в строку MyMessageBox
, MyMessageBox
еще не определен. Компилятор понятия не имеет MyMessageBox
существует, поэтому не может понять смысл вашего члена класса.
Вам необходимо убедиться, что MyMessageBox
определен, прежде чем использовать его в качестве члена. Это решается путем изменения порядка определения. Однако у вас есть циклическая зависимость: если вы перемещаете MyMessageBox
выше User
, тогда в определении MyMessageBox
имя User
не будет определено!
Что вы можете сделать, это forward declare User
; то есть объявить его, но не определять. Во время компиляции тип, объявленный, но не определенный, называется неполным.
Рассмотрим более простой пример:
struct foo; // foo is *declared* to be a struct, but that struct is not yet defined
struct bar
{
// this is okay, it 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 now defined
MyMessageBox dataMsgBox;
};
Вы не можете сделать это наоборот: как уже упоминалось, член класса должен иметь определение. (Причина в том, что компилятор должен знать, сколько занимает память User
, и знать, что ему нужно знать размер его членов.) Если бы вы сказали:
class MyMessageBox;
class User
{
public:
// size not available! it an incomplete type
MyMessageBox dataMsgBox;
};
Это не сработает, так как пока не знает размер.
На боковой ноте эта функция:
void sendMessage(Message *msg, User *recvr);
Вероятно, не следует брать ни один из указателей. Вы не можете отправить сообщение без сообщения, а также не можете отправить сообщение без отправки его пользователю. И обе эти ситуации можно выразить, передав null в качестве аргумента для любого параметра (null - это абсолютно допустимое значение указателя!)
Скорее используйте ссылку (возможно, const):
void sendMessage(const Message& msg, User& recvr);