C + + 中的“ X 不命名类型”错误

我申报了两个类别如下:

class User
{
public:
MyMessageBox dataMsgBox;
};


class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message> *dataMessageList;
};

当我尝试使用 gcc 编译它时,它会出现以下错误:

MyMessageBox 不命名类型

627515 次浏览

当编译器编译类 User并到达 MyMessageBox行时,还没有定义 MyMessageBox。编译器不知道 MyMessageBox的存在,因此无法理解类成员的含义。

您需要确保 MyMessageBox是定义为 之前的,并将其用作成员。这可以通过颠倒定义顺序来解决。但是,您有一个循环依赖项: 如果您将 MyMessageBox移到 User之上,那么在 MyMessageBox的定义中将不会定义名称 User

您可以做的是 前方声明 User; 也就是说,声明它,但不定义它。在编译期间,声明但未定义的类型称为 不完整类型。 考虑一个更简单的例子:

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;
}

通过向前声明 UserMyMessageBox仍然可以形成指向它的指针或引用:

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;
};

不能采取相反的方法: 正如前面提到的,类成员需要有一个定义。(原因是编译器需要知道 User占用了多少内存,并且需要知道它的成员的大小。)如果你说:

class MyMessageBox;


class User
{
public:
// size not available! it's an incomplete type
MyMessageBox dataMsgBox;
};

没用的,因为它还不知道尺寸。


值得注意的是,这种功能:

 void sendMessage(Message *msg, User *recvr);

也许不应该用指针来记录。您不能在没有消息的情况下发送消息,也不能在没有用户的情况下发送消息。这两种情况都可以通过将 null 作为参数传递给任何一个参数来表示(null 是一个完全有效的指针值!)

相反,使用引用(可能是 const) :

 void sendMessage(const Message& msg, User& recvr);

在使用原型之前,您必须声明它:

class User;


class MyMessageBox
{
public:
void sendMessage(Message *msg, User *recvr);
Message receiveMessage();
vector<Message> *dataMessageList;
};


class User
{
public:
MyMessageBox dataMsgBox;
};

编辑 : 交换类型

C + + 编译器只处理输入一次。您使用的每个类必须首先定义。在定义之前使用 MyMessageBox。在这种情况下,您可以简单地交换两个类定义。

  1. 向前声明用户
  2. 将 MyMessageBox 的声明放在 User 之前

您需要在 User 之前定义 MyMessageBox ——因为 User 包含 MyMessageBox按价值计算的对象(因此编译器应该知道它的大小)。

此外,MyMessageBox 还需要 前方声明 User,因为 MyMessageBox 包含 User * 类型的成员。

相关的一点是,如果你有:

    class User; // let the compiler know such a class will be defined


class MyMessageBox
{
public:
User* myUser;
};


class User
{
public:
// also ok, since it's now defined
MyMessageBox dataMsgBox;
};

那么这也可以,因为 User 在 MyMessageBox 中被定义为一个指针

在 C + + 中,总是鼓励每个头文件有一个类,参见 SO [ 1]中的讨论。 GManNickG 的答案告诉我们为什么会发生这种情况。但是解决这个问题的最好方法是将 User类放在一个头文件(User.h)中,将 MyMessageBox类放在另一个头文件(MyMessageBox.h)中。然后在你的 User.h你包括 MyMessageBox.h和在 MyMessageBox.h你包括 User.h。不要忘记“ include gaurds”[ 2] ,这样您的代码才能成功编译。