Quando o compilador compila a classe User
e chega à MyMessageBox
linha, MyMessageBox
ainda não foi definido. O compilador não tem ideiaMyMessageBox
, portanto, não pode entender o significado do seu aluno.
Você precisa ter certeza de que MyMessageBox
está definido antes de usá-lo como membro. Isso é resolvido revertendo a ordem de definição. No entanto, você tem uma dependência cíclica: se você se mover MyMessageBox
acima User
, na definição do MyMessageBox
nome User
não será definido!
O que você pode fazer é declarar adiante User
; ou seja, declare-o, mas não o defina. Durante a compilação, um tipo declarado mas não definido é chamado de tipo incompleto . Considere o exemplo mais simples:
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;
}
Ao declarar adiante User
, MyMessageBox
ainda é possível formar um ponteiro ou uma referência a ele:
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;
};
Você não pode fazer o contrário: como mencionado, um aluno precisa ter uma definição. (O motivo é que o compilador precisa saber quanta memória User
ocupa e saber que precisa saber o tamanho de seus membros.) Se você disser:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
Não funcionaria, pois ainda não sabe o tamanho.
Em uma nota lateral, esta função:
void sendMessage(Message *msg, User *recvr);
Provavelmente não deve pegar nenhum deles por ponteiro. Você não pode enviar uma mensagem sem uma mensagem, nem pode enviar uma mensagem sem um usuário para enviá-la. E ambas as situações são expressáveis passando null como argumento para qualquer parâmetro (null é um valor de ponteiro perfeitamente válido!)
Em vez disso, use uma referência (possivelmente const):
void sendMessage(const Message& msg, User& recvr);