类名未在C ++中命名类型

时间:2010-08-31 10:57:07

标签: c++

我刚开始用C ++编程,我试图创建两个类,其中一个将包含另一个。

档案A.h

#ifndef _A_h
#define _A_h

class A{
    public:
        A(int id);
    private:
        int _id;
        B _b; // HERE I GET A COMPILATION ERROR: B does not name a type
};

#endif

档案A.cpp

#include "A.h"
#include "B.h"
#include <cstdio>

A::A(int id): _id(id), _b(){
    printf("hello\n the id is: %d\n", _id);
}

档案B.h

#ifndef _B_h
#define _B_h

class B{
    public:
        B();
};
#endif

档案B.cpp

#include "B.h"
#include <cstdio>

B::B(){
    printf("this is hello from B\n");
}

我首先编译B类然后编译A类,但后来我收到错误消息:

  

A.h:9:错误:'B'没有命名类型

如何解决此问题?

9 个答案:

答案 0 :(得分:34)

预处理器将文件A.hB.h的内容准确插入到include语句出现的位置(这实际上只是复制/粘贴)。当编译器解析A.cpp时,它会在知道类A之前找到类B的声明。这会导致您看到的错误。有两种方法可以解决这个问题:

  1. B.h中加入A.h。将头文件包含在需要它们的文件中通常是个好主意。如果你依赖于通过另一个标题进行间接包含,或者在编译单元(cpp-file)中包含一个特殊的包含顺序,这只会让你和其他人混淆,因为项目变大了。
  2. 如果在类B中使用类型A的成员变量,编译器需要知道B的完整和完整声明,因为它需要创建内存-A的布局。另一方面,如果您使用指针或B的引用,则前向声明就足够了,因为编译器需要为指针或引用保留的内存与类定义无关。这看起来像这样:

    class B; // forward declaration        
    class A {
    public:
        A(int id);
    private:
        int _id;
        B & _b;
    };
    

    这对于避免标题之间的循环依赖非常有用。

  3. 我希望这会有所帮助。

答案 1 :(得分:3)

您必须先B.h加入A.hB b;在你加入B.h之前没有任何意义。

答案 2 :(得分:2)

在“A.h”中加入“B.h”。这会在编译'A'时为编译器声明'B'。

OP的第一个项目符号。

$ 3.4.1 / 7 -

  

“a。定义中使用的名称   成员函数之外的类X.   body或嵌套类定义27)   应在其中一个中声明   以下方式:

     

- 在使用之前   class X或者是基类的成员   X(10.2),

     

- 如果X是嵌套的   Y级(9.7)之前的类   在Y中定义X,或者应该是a   Y基类的成员(这个   查找依次适用于Y.   封闭课程,从...开始   最里面的封闭类),28)或

     

- 如果   X是本地类(9.8)或是   之前的本地类的嵌套类   块中类X的定义   包含X类的定义,   或

     

- 如果X是命名空间N的成员,   或者是类的嵌套类   是N的成员,或者是本地班级   或本地类中的嵌套类   作为N的成员的函数,   在定义X类之前   名称空间N或N的一个封闭   命名空间“。

答案 3 :(得分:2)

问题是您需要在B.h文件中加入A.h。问题是在A的定义中,编译器仍然不知道B是什么。您应该包括您正在使用的所有类型的所有定义。

答案 4 :(得分:1)

当你定义A类时,在A.h中,你明确地说该类有一个成员B.

你必须在“A.h”中加入“Bah”

答案 5 :(得分:1)

你是否错过了A.h中的#include“B.h”?

答案 6 :(得分:1)

注意:由于使用相同关键字进行搜索的用户将进入此页面,因此我添加了此答案,这并不是上述情况下此编译器错误的原因。

当我在某个文件中声明一个enum且其中一个元素的符号与类名相同的符号时,我遇到了这个错误。

例如如果我在某个文件中声明了enum = {A, B, C},而该文件又在另一个文件中声明了class A的对象。

这引发了相同的编译器错误消息,提到了Class A does not name a type。在我的情况下,没有循环依赖。

因此,在使用C ++命名类和声明枚举(在其他文件中可能是可见的,导入的和在外部使用的枚举)时要小心。

答案 7 :(得分:0)

今天我的问题的解决方案与这里的其他回答略有不同。

就我而言,问题是由包含链中的头文件之一结尾处缺少右括号(})引起的。

从本质上讲,正在发生的事情是A包含B。由于B在文件中某处缺少},因此在B中找不到正确的A中的定义。

起初,我认为我有循环依赖关系,并添加了前向声明B。但是随后,它开始抱怨B中的某些内容是不完整的类型。这就是我想仔细检查文件中语法错误的方式。

答案 8 :(得分:-1)

实际上发生在我身上,是因为我错误地将源文件命名为“ something.c” 而不是“ something.cpp”。 希望这对有相同错误的人有所帮助。