Lorsque le compilateur compile la classe User
et accède à la MyMessageBox
ligne, MyMessageBox
n'a pas encore été défini. Le compilateur n'a aucune idée de l' MyMessageBox
existence et ne peut donc pas comprendre la signification de votre membre de classe.
Vous devez vous assurer qu'il MyMessageBox
est 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 MyMessageBox
ci User
- dessus , la définition du MyMessageBox
nom User
ne 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
, MyMessageBox
peut 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 User
prend 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);