牛骨文教育服务平台(让学习变的简单)

没有躲过的坑--头文件相互包含(Compiler error C2653: not a class or namespace name)

最近被自己坑儿了一把,改别人的代码,最后编译器这样报错的:

error C2653: not a class or namespace name

简单描述一下: 
有一个类A,声明和实现分别位于 a.h和a.cc中 
有一个类B,声明和实现分别位于 b.h和b.cc中 
类A的某个成员函数需要B类类型作为参数 
类B的某个成员函数需要A类类型作为参数

a.h文件如下:

#ifndef A_H_
#define A_H_

#include "b.h"
class A
{
public:
    enum State
    {
        RIGHT = 0;
        ERROR = 1;
    }
    void send (B b);
    ...
};
#endif

a.cc文件省略,无影响

b.h文件是这样的:

#ifndef B_H_
#define B_H_

#include "a.h"
class B
{
public:

    void send (A::State state);
    ...
};

此时呢,编译器就会报错: 
error C2653: A not a class or namespace name

这时候我们的第一反应往往是查看b.h中是否包含了A类所在的头文件,即是否包含了a.h文件。

但是坑爹的是,我们明明包含了呀,怎么还会报错呢?

好吧,就是相互包含的事儿,编译器已经蒙掉了。 
简而言之就是不要包含不必要的头文件。

偶对了 差点忘告诉怎么修改了?

首先,我们是把类A和B放在了一个命名空间中,即对A和B都进行了 namespace KENG{ }封装。

所以这个时候,我们可以在A中不包含B的头文件,而改成前置声明、、、、、

#ifndef A_H_
#define A_H_

class B;
class A
{
public:
    enum State
    {
        RIGHT = 0;
        ERROR = 1;
    }
    void send (B b);
    ...
};
#endif

大功告成! 
我们用#ifndef躲过了重复包含头文件的坑儿,但是我们也不能肆无忌惮的包含,更要避免相互包含的情况!!!