Lorsque le compilateur compile la classe User
et arrive à l' MyMessageBox
ligne, MyMessageBox
n'a pas encore été défini. Il n'a aucune idée qu'il existe, ne peut pas comprendre le sens de votre membre de la classe.
Vous devez assurez - MyMessageBox
est défini avant de l'utiliser comme un membre. Ce problème est résolu par l'inversion de la définition de l'ordre. Cependant, vous avez une dépendance cyclique: si vous déplacez MyMessageBox
- dessus User
, puis dans la définition de l' MyMessageBox
nom User
ne sera pas défini!
Ce que vous pouvez faire est de déclarer avant User
, à déclarer, mais ne le définissent pas. Lors de la compilation, un type qui est déclarée mais non défini est appelé un type incomplète.
Considérons l'exemple 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;
}
Par l'avant de déclarer User
, MyMessageBox
peut encore former un pointeur ou une référence à ça:
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 peut pas le faire dans l'autre sens: comme mentionné, un membre de la classe doit avoir une définition. (La raison en est que le compilateur a besoin de savoir combien de mémoire User
, et de savoir qu'il a besoin de savoir la taille de ses membres.) Si vous dites:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
Ça ne marcherait pas, car il ne sait pas la taille encore.
Sur une note de côté, cette fonction:
void sendMessage(Message *msg, User *recvr);
Il est préférable de ne pas prendre l'une de ces par pointeur. Vous ne pouvez pas envoyer un message, sans un message, et vous ne pouvez envoyer un message à un utilisateur d'envoyer. Et ces deux situations sont exprimables en passant null comme un argument pour chaque paramètre (la valeur null est parfaitement valide la valeur du pointeur!)
Plutôt, utilisez une référence (éventuellement const):
void sendMessage(const Message& msg, User& recvr);