C++ 关于redefinition

  • Post author:
  • Post category:其他

今天遇到了c++编译中的redefinition的问题。有两种情况,一种是两个cpp文件共同include一个.h文件中一个定义。第二种是只有一个cpp文件,但是cpp文件中include的.h文件中的定义,被其他.h多次include。说的有点复杂,举个例子。

有三个文件a.h  b.h  c.cpp

//a.h

int global;

//b.h

#include “a.h”

//c.cpp

#include “a.h”

#include “b.h”

int main()

{}

如上的三个文件进行编译g++ c.cpp会出现重定义的错误,请注意这里是在编译阶段报错,说明编译c.cpp时,发现了一个变量的多次

In file included from b.h:1:0,
                 from c.cpp:2:
a.h:3:5: error: redefinition of ‘int global’

a.h:3:5: error: ‘int global’ previously declared here

因为在c.cpp中包含了a.h 和b.h  而b.h又include 了a.h所以global变量就被多次定义了

解决方案使用条件编译,让a.h中的定义只被编译一次。

修改a.h为

#ifndef _A_H_
#define _A_H_
int global;

#endif

这样就可以编译通过,解决重定义的问题。

第二种情况,依然有三个文件a.h b.cpp c.cpp

//a.h

#ifndef _A_H_
#define _A_H_
int global;
#endif

//b.cpp

#include “a.h”

//c.cpp

#include “a.h”
int main()
{

}

上面的两个cpp文件同时包含了同一个.h文件,在编译这两个.cpp文件时会出错

/tmp/ccKwU8xx.o:(.bss+0x0): multiple definition of `global’
/tmp/ccX7atev.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status

我们可以看到,这一次报错和上一次报错有些不同,这次报错编译两个cpp文件都没有问题,但是在链接阶段出现了问题

说明每个cpp文件都定义了a.h中的global变量,两个cpp有两个global的定义,在编译过程中没有错,但是在链接的时候发现有两个同名的变量导致出错。

出错的原因是,编译的过程是先将每一个.cpp文件单独编译成.o文件,然后再把这些.o文件用连接器连接起来。所以我们看到在编译的过程中没有发生错误,但是在链接中发生了错误。

解决方法,我们不要把变量的定义写在.h文件中,只把声明写在.h里,而把定义写在cpp文件中,可以避免这个问题。

我们用一个函数而不是一个变量来说明这个问题

//a.h

#ifndef _A_H_
#define _A_H_
int fun()
{
    return 0;
}
#endif

//b.cpp

#include “a.h”

//c.cpp

#include “a.h”
#include <iostream>
using namespace std;
int main()
{
    cout << fun()<<endl;
}

编译b.cpp和c.cpp   g++ b.cpp c.cpp出现刚才描述的连接时出错的问题

/tmp/ccOUoDIl.o: In function `fun()’:
c.cpp:(.text+0x0): multiple definition of `fun()’
/tmp/ccGyWBKj.o:b.cpp:(.text+0x0): first defined here
collect2: ld returned 1 exit status

我们把fun()的实现写在一个a.cpp中去

修改a.h

//a.h

#ifndef _A_H_
#define _A_H_
int fun()
#endif

增加文件a.cpp

//a.cpp

#include “a.h”
int fun()
{
    return 0;
}

编译a.cpp b.cpp c.cpp  (g++ a.cpp b.cpp c.cpp)即可编译成功执行


版权声明:本文为yushiyaogg原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。