在C\C++的代码的初学阶段,常常会出现"XXX重定义"、”,或“XXX未定义”等问题,尤其是在初次接触比较复杂的代码的时候,各种文件关系复杂,在编译时猛然蹦出这么一个问题,乍一看让人有点摸不着头脑。为了详细介绍这个问题,下面将引用一个简单的来展示这种bug的出现,并给出相应的解决办法。
以C++为例,假设有两个功能A.cpp\B.cpp,以下为A.cpp对于的.h文件(只做演示)
class A
{
};
B.h文件如下
#include "A.h"
class B{
};
首先,建一个main.cpp,具体如下
#include "A.h"
#include "B.h"
int main()
{
return 0;
}
此处只用作演示上文提及的错误生成过程,所以啥也没写。
而当我们编译的时候,神奇的事情出现了,编译器弹出来这么一个错误:
由于VS现在已经有中文翻译了,所以出现那个令人绝望的“redefined XXX ...”已经不再出现,但是这个问题本身依然让人觉得有点摸不着头脑。实际上,这是由于C\C++编译器在编译的预处理阶段是将include " .h"中的内容直接插入对应的.cpp文件中,所以,既包含了"A.h",又包含了“B.h”的main.cpp中就会出现两个A类,重定义即由此而来。
具体解决方法:
本文采用的是用h文件中的宏来解决这一问题,具体为在A.h中加入
#ifndef _A_H_
#define _A_H_
void f();
class A
{
};
#endif // !_A_H_
使得A类值插入一次,因此解决了重定义的问题。
同样,若在.h文件中定义变量global,如
#ifndef _A_H_
#define _A_H_
int global;
void f();
class A
{
};
#endif // !_A_H_
同时在a.cpp中写一个函数
#include "a.h"
void fun() {
global++;
}
在进行编译时出现了这样一个错误
又感觉很头大啊,错误在哪里呢?
咱们来详细看一下编译发生的过程:
在上面我们不难发现,每个cpp文件都是单独编译的,其只有到最后链接的时候才会在一起出现,结合上面的知识我们就知道了,每个包含include " a.h"的cpp都会生成一个int global变量,但在编译是各不影响,直到链接时才会出现“重定义”这一问题,这就是为什么我们不能在.h文件中定义变量,而要将全局变量通过extern关键字甩出来的原因了。
写在最后:这篇文章是从翁恺老师的C++课中总结出来的,尽管是一些在初学阶段出现的问题,但其中展现出来的C\C++编译器的相关知识却非常深刻,听完之后收益良多