Wann der Compiler die Klasse kompiliert Userund zur MyMessageBoxZeile gelangt , MyMessageBoxwurde noch nicht definiert. Der Compiler hat keine Ahnung MyMessageBox, kann also die Bedeutung Ihres Klassenmitglieds nicht verstehen.
Sie müssen sicherstellen, dass MyMessageBoxes definiert ist, bevor Sie es als Mitglied verwenden. Dies wird durch Umkehren der Definitionsreihenfolge gelöst. Sie haben jedoch eine zyklische Abhängigkeit: Wenn Sie nach MyMessageBoxoben gehen User, wird in der Definition des MyMessageBoxNamens Usernicht definiert!
Was Sie tun können, ist vorwärts zu deklarieren User ; das heißt, deklarieren Sie es, aber definieren Sie es nicht. Während der Kompilierung wird ein deklarierter, aber nicht definierter Typ als unvollständiger Typ bezeichnet . Betrachten Sie das einfachere Beispiel:
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;
}
Durch die nach vorne erklärt User, MyMessageBoxkann immer noch einen Zeiger oder Verweis auf sie bilden:
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;
};
Sie können dies nicht umgekehrt tun: Wie bereits erwähnt, muss ein Klassenmitglied eine Definition haben. (Der Grund dafür ist, dass der Compiler wissen muss, wie viel Speicher belegt Userwird, und dass er die Größe seiner Mitglieder kennen muss.) Wenn Sie sagen würden:
class MyMessageBox;
class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};
Es würde nicht funktionieren, da es die Größe noch nicht kennt.
Nebenbei bemerkt, diese Funktion:
void sendMessage(Message *msg, User *recvr);
Wahrscheinlich sollte keiner von beiden per Zeiger genommen werden. Sie können keine Nachricht ohne Nachricht senden, noch können Sie eine Nachricht ohne einen Benutzer senden, an den Sie sie senden können. Und beide Situationen können ausgedrückt werden, indem null als Argument an einen der Parameter übergeben wird (null ist ein vollkommen gültiger Zeigerwert!).
Verwenden Sie stattdessen eine Referenz (möglicherweise const):
void sendMessage(const Message& msg, User& recvr);