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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2133250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:12:25  来源:igfitidea点击:

"X does not name a type" error in C++

c++windowstypes

提问by Rakesh K

I have two classes declared as below:

我有两个类声明如下:

class User
{
public:
  MyMessageBox dataMsgBox;
};

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

When I try to compile it using gcc, it gives the following error:

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

MyMessageBox does not name a type

MyMessageBox 未命名类型

回答by GManNickG

When the compiler compiles the class Userand gets to the MyMessageBoxline, MyMessageBoxhas not yet been defined. The compiler has no idea MyMessageBoxexists, so cannot understand the meaning of your class member.

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

You need to make sure MyMessageBoxis defined beforeyou use it as a member. This is solved by reversing the definition order. However, you have a cyclic dependency: if you move MyMessageBoxabove User, then in the definition of MyMessageBoxthe name Userwon't be defined!

将其用作成员之前,您需要确保MyMessageBox已定义。这是通过颠倒定义顺序来解决的。然而,你有一个循环依赖:如果你在上面移动,那么在名称的定义中将不会被定义!MyMessageBoxUserMyMessageBoxUser

What you can do is forward declareUser; that is, declare it but don't define it. During compilation, a type that is declared but not defined is called an incomplete type. Consider the simpler example:

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

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

By forward declaring User, MyMessageBoxcan still form a pointer or reference to it:

通过前向声明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;
};

You cannotdo this the other way around: as mentioned, a class member needs to have a definition. (The reason is that the compiler needs to know how much memory Usertakes up, and to know that it needs to know the size of its members.) If you were to say:

不能反过来这样做:如前所述,类成员需要有一个定义。(原因是编译器需要知道User占用了多少内存,并且知道它需要知道其成员的大小。)如果你说:

class MyMessageBox;

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

It wouldn't work, since it doesn't know the size yet.

这是行不通的,因为它还不知道大小。



On a side note, this function:

附带说明一下,此功能:

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

Probably shouldn't take either of those by pointer. You can't send a message without a message, nor can you send a message without a user to send it to. And both of those situations are expressible by passing null as an argument to either parameter (null is a perfectly valid pointer value!)

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

Rather, use a reference (possibly const):

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

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

回答by Brian R. Bondy

  1. Forward declare User
  2. Put the declaration of MyMessageBox before User
  1. 转发声明用户
  2. 将 MyMessageBox 的声明放在 User 之前

回答by Alexander Poluektov

You need to define MyMessageBox before User -- because User include object of MyMessageBox by value(and so compiler should know its size).

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

Also you'll need to forward declareUser befor MyMessageBox -- because MyMessageBox include member of User* type.

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

回答by awesomeamyg

On a related note, if you had:

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

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

Then that would also work, because the User is defined in MyMessageBox as a pointer

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

回答by MSalters

C++ compilers process their input once. Each class you use must have been defined first. You use MyMessageBoxbefore you define it. In this case, you can simply swap the two class definitions.

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

回答by Alex LE

You must declare the prototype it before using it:

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

class User;

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

class User
{
public:
 MyMessageBox dataMsgBox;
};

edit: Swapped the types

编辑:交换类型

回答by Chehadeh

It is always encouraged in C++ that you have one class per header file, see this discussion in SO [1]. GManNickG answer's tells why this happen. But the best way to solve this is to put Userclass in one header file (User.h) and MyMessageBoxclass in another header file (MyMessageBox.h). Then in your User.hyou include MyMessageBox.hand in MyMessageBox.hyou include User.h. Do not forget "include gaurds" [2] so that your code compiles successfully.

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