关于windows:“X没有在C ++中命名类型”错误

“X does not name a type” error in C++

我有两个类声明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
class User
{
public:
  MyMessageBox dataMsgBox;
};

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

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

MyMessageBox does not name a type


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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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仍然可以形成指针或引用它:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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占用了多少内存,并且知道它需要知道其成员的大小。)如果你要说:

1
2
3
4
5
6
7
8
class MyMessageBox;

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

它不起作用,因为它还不知道尺寸。

另外,这个功能:

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

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

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

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


  • 转发声明用户
  • 将MyMessageBox的声明放在User之前

  • 在相关的说明中,如果您有:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        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中被定义为指针


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

    此外,您还需要转发声明User befor MyMessageBox - 因为MyMessageBox包含User *类型的成员。


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


    在C ++中总是鼓励每个头文件有一个类,请参阅SO [1]中的这个讨论。
    GManNickG回答说明了为什么会发生这种情况。但解决此问题的最佳方法是将User类放在另一个头文件(MyMessageBox.h)中的一个头文件(User.h)和MyMessageBox类中。然后在User.h中包含MyMessageBox.h,在MyMessageBox.h中包含User.h。不要忘记"包括gaurds"[2],以便您的代码成功编译。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class User;

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

    class User
    {
    public:
     MyMessageBox dataMsgBox;
    };

    编辑:交换类型