Lorsque le compilateur compile la classe Useret accède à la MyMessageBoxligne, MyMessageBoxn'a pas encore été défini. Le compilateur n'a aucune idée de l' MyMessageBoxexistence et ne peut donc pas comprendre la signification de votre membre de classe.
Vous devez vous assurer qu'il MyMessageBoxest défini avant de l' utiliser en tant que membre. Ceci est résolu en inversant l'ordre des définitions. Cependant, vous avez une dépendance cyclique: si vous vous déplacez MyMessageBoxci User- dessus , la définition du MyMessageBoxnom Userne sera pas définie!
Ce que vous pouvez faire, c'est déclarer en avant User ; autrement dit, déclarez-le mais ne le définissez pas. Lors de la compilation, un type déclaré mais non défini est appelé type incomplet . Prenons l'exemple le plus simple:
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;
}
En déclarant en avant User, MyMessageBoxpeut toujours former un pointeur ou une référence à celui-ci:
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;
};
Vous ne pouvez pas faire cela dans l'autre sens: comme mentionné, un membre de la classe doit avoir une définition. (La raison est que le compilateur a besoin de savoir combien de mémoire Userprend et de savoir qu'il a besoin de connaître la taille de ses membres.) Si vous deviez dire:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
Cela ne fonctionnerait pas, car il ne connaît pas encore la taille.
En passant, cette fonction:
void sendMessage(Message *msg, User *recvr);
Ne devrait probablement pas prendre l'un ou l'autre de ces points par pointeur. Vous ne pouvez pas envoyer un message sans message, ni envoyer un message sans un utilisateur à qui l'envoyer. Et ces deux situations sont exprimables en passant null comme argument à l'un ou l'autre des paramètres (null est une valeur de pointeur parfaitement valide!)
Utilisez plutôt une référence (éventuellement const):
void sendMessage(const Message& msg, User& recvr);