编码中发现一个奇怪的编译错误,花了很长时间才找到问题所在。下面把重现这个问题的最精简的代码贴出来:

/**//*
MyClass.h
存在一个namespace和一个类
*/

#ifndef _MY_CLASS_H_
#define _MY_CLASS_H_

namespace MySpace

...{

class MyClass

...{
public:
int Field;
};

}

#endif
下面的一个文件声明一个全局的指针,因为仅仅指示声明,所以尽量不包含其他文件:

/**//*
global.h
声明一个全局的指针
*/

#ifndef _GLOBAL_H_
#define _GLOBAL_H_

class MyClass; //对存在的类型做一个声明,不引入定义的头文件
extern MyClass* g_Obj;

#endif
下面的文件使用全局变量和类型:

/**//*
use.cpp
这个文件里面使用全局对象指针和类型
*/

#include "MyClass.h"
#include "global.h"

void test1()

...{
g_Obj = new MyClass();
g_Obj->Field = 1;
}


/**//*
g++ -o use.o -c use.cpp -g -Wall
*/
编译use.cpp,产生了很多编译错误:
你可能会说,得加上using namespace MySpace; 实际上,这句加进去还是编译不过。当然,如果在global.h中包含MyClass.h,应该就能够编译过去了。但是我不想这么做,对于一个指针类型,其类型只要声明就好,不需要引入定义的。包含太多的头文件会引发编译问题的。
试了很多办法,最后发现,在use.cpp中的#include "MyClass.h"后加入一行:using MySpace::MyClass; 然后代码就能够编译过去了。
总结一下:对于存在于namespace中的类型,如果在某个头文件中对类型声明过,则在使用的时候要注意:
1、类型的定义文件包含在前(#include "MyClass.h")
2、声明namespace中的类型(using MySpace::MyClass;)
3、然后包含全局指针的声明文件(#include "global.h")
4、在其后使用就没问题了

/**//*
MyClass.h
存在一个namespace和一个类
*/
#ifndef _MY_CLASS_H_
#define _MY_CLASS_H_
namespace MySpace
...{
class MyClass
...{
public:
int Field;
};
}
#endif

/**//*
global.h
声明一个全局的指针
*/
#ifndef _GLOBAL_H_
#define _GLOBAL_H_
class MyClass; //对存在的类型做一个声明,不引入定义的头文件
extern MyClass* g_Obj;
#endif

/**//*
use.cpp
这个文件里面使用全局对象指针和类型
*/
#include "MyClass.h"
#include "global.h"
void test1()
...{
g_Obj = new MyClass();
g_Obj->Field = 1;
}

/**//*
g++ -o use.o -c use.cpp -g -Wall
*/
| only_use.cpp: In function `void test1()': only_use.cpp:11: error: invalid use of undefined type `struct MyClass' global.h:9: error: forward declaration of `struct MyClass' only_use.cpp:12: error: invalid use of undefined type `struct MyClass' global.h:9: error: forward declaration of `struct MyClass' |
你可能会说,得加上using namespace MySpace; 实际上,这句加进去还是编译不过。当然,如果在global.h中包含MyClass.h,应该就能够编译过去了。但是我不想这么做,对于一个指针类型,其类型只要声明就好,不需要引入定义的。包含太多的头文件会引发编译问题的。
试了很多办法,最后发现,在use.cpp中的#include "MyClass.h"后加入一行:using MySpace::MyClass; 然后代码就能够编译过去了。
总结一下:对于存在于namespace中的类型,如果在某个头文件中对类型声明过,则在使用的时候要注意:
1、类型的定义文件包含在前(#include "MyClass.h")
2、声明namespace中的类型(using MySpace::MyClass;)
3、然后包含全局指针的声明文件(#include "global.h")
4、在其后使用就没问题了
解决命名空间引起的编译错误
本文介绍了一种由于命名空间使用不当导致的编译错误,并提供了解决方案。通过在使用命名空间类型前声明该类型,可以避免编译失败。
416

被折叠的 条评论
为什么被折叠?



