当编译器编译类 User
并到达代码中的 MyMessageBox
行时,MyMessageBox
尚未定义。编译器不知道 MyMessageBox
的存在,因此无法理解您的类成员的含义。
在使用它作为成员之前,您需要确保 MyMessageBox
已经被定义了。这可以通过反转定义顺序来解决。但是,您会遇到循环依赖:如果您将 MyMessageBox
移至 User
上面,则在 MyMessageBox
的定义中,名称 User
将不会被定义!
您可以进行 前向声明 User
;也就是声明它但不定义它。在编译期间,已声明但未定义的类型称为不完全类型。
考虑以下简单示例:
struct foo;
struct bar
{
foo* fp;
void some_func(foo& fr);
};
struct foo
{
int fooInt;
double fooDouble;
};
void bar::some_func(foo& fr)
{
fr.fooInt = 111605;
fr.foDouble = 123.456;
}
通过前置声明 User
,MyMessageBox
仍可以形成指向它的指针或引用:
class User;
class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message>* dataMessageList;
};
class User
{
public:
MyMessageBox dataMsgBox;
};
你不能反过来这样做:如上所述,类成员需要有定义。(原因是编译器需要知道User
占用多少内存,为了知道这一点,它需要知道其成员的大小。)如果您这样说:
你无法以相反的方式进行此操作:如前所述,一个类成员需要有定义。(原因是编译器需要知道User
占用多少内存,而要知道这一点,它需要知道其成员的大小。)如果你说:
class MyMessageBox;
class User
{
public:
MyMessageBox dataMsgBox;
};
由于它还不知道大小,所以它无法工作。
另外一件事,这个函数:
void sendMessage(Message *msg, User *recvr);
不应该使用指针来传递这两个参数。没有消息时不能发送消息,也没有接收者时不能发送消息。这两种情况都可以通过将 null 作为参数传递来表示(null 是一个完全有效的指针值!)
相反,应该使用引用(可能是 const 引用):
void sendMessage(const Message& msg, User& recvr);
g++
而不是gcc
来编译 C++ 文件。 - Lorenzo Battilocchi