简体   繁体   English

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

[英]"X does not name a type" error in C++

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 没有命名类型

When the compiler compiles the class User and gets to the MyMessageBox line, MyMessageBox has not yet been defined. 当编译器编译类User并进入MyMessageBox行时,尚未定义MyMessageBox The compiler has no idea MyMessageBox exists, so cannot understand the meaning of your class member. 编译器不知道MyMessageBox存在,因此无法理解您的类成员的含义。

You need to make sure MyMessageBox is defined before you use it as a member. 将其用作成员之前,您需要确保定义了MyMessageBox This is solved by reversing the definition order. 这可以通过颠倒定义顺序来解决。 However, you have a cyclic dependency: if you move MyMessageBox above User , then in the definition of MyMessageBox the name User won't be defined! 但是,您有一个循环依赖:如果您将MyMessageBox移动到User之上,那么在MyMessageBox的定义中将不会定义User的名称!

What you can do is forward declare User ; 你可以做的是转发声明 User ; 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: 考虑一个更简单的例子:

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 , MyMessageBox can 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 cannot do 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 User takes 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);
  1. Forward declare User 转发声明用户
  2. Put the declaration of MyMessageBox before User 将MyMessageBox的声明放在User之前

C++ compilers process their input once. C ++编译器处理它们的输入一次。 Each class you use must have been defined first. 您使用的每个类必须首先定义。 You use MyMessageBox before you define it. 在定义之前使用MyMessageBox In this case, you can simply swap the two class definitions. 在这种情况下,您可以简单地交换两个类定义。

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 declare User befor MyMessageBox -- because MyMessageBox include member of User* type. 此外,您还需要转发声明 User befor MyMessageBox - 因为MyMessageBox包含User *类型的成员。

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中被定义为指针

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 编辑 :交换类型

It is always encouraged in C++ that you have one class per header file, see this discussion in SO [ 1 ]. 在C ++中总是鼓励每个头文件有一个类,请参阅SO [ 1 ]中的这个讨论。 GManNickG answer's tells why this happen. GManNickG回答说明了为什么会发生这种情况。 But the best way to solve this is to put User class in one header file ( User.h ) and MyMessageBox class in another header file ( MyMessageBox.h ). 但解决此问题的最佳方法是将User类放在一个头文件( User.h )中,将MyMessageBox类放在另一个头文件( MyMessageBox.h )中。 Then in your User.h you include MyMessageBox.h and in MyMessageBox.h you include User.h . 然后在您的User.h包含MyMessageBox.h ,在MyMessageBox.h包含User.h Do not forget "include gaurds" [ 2 ] so that your code compiles successfully. 不要忘记“包括gaurds”[ 2 ],以便您的代码成功编译。

In my case, it turned out that this very uninformative error was caused by a circular dependency.在我的例子中,事实证明这个非常无意义的错误是由循环依赖引起的。 Instead of代替

// A.hpp
#include "B.hpp"

class A {
    B b;
}

// B.hpp
#include "A.hpp"

class B {
    A a;
}

I changed the second file to我将第二个文件更改为

// B.hpp
class A;

class B {
    A a;
}

... and all the compiler errors, as well as the sudden lack of syntax highlighting in my IDE, disappeared. ...所有编译器错误,以及我的 IDE 中突然缺少语法突出显示,都消失了。

I did need to later put a #include "A.hpp" at the top of the B.cpp file, but that's fine, because there's no circular dependency in that case ( B.cpp -> A.hpp -> B.hpp -> / ).稍后我确实需要在B.cpp文件的顶部放置一个#include "A.hpp" ,但这很好,因为在这种情况下没有循环依赖( B.cpp -> A.hpp -> B.hpp -> / )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM