重复定义问题
Posted youngbig
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了重复定义问题相关的知识,希望对你有一定的参考价值。
这里说的重复定义其实包含两个意思:
1,头文件重复包含
2,变量或函数重复定义
对问题1,比如这样:
有一个头文件 c.h 。
在头文件a.h中
#include "c.h"
在头文件b.h中
#include "a.h"
#include "c.h"
这样就会导致重复包含,解决办法如下:
在c.h中
#ifndef C_H #define C_H //c.h中所有内容 #endinf
这样,在第二次引用"c.h"时,由于已经定义了C_H,将不会再次引用"c.h"
当然,也要避免在头文件里include,如果include是写在cpp里面的话,就不会出现相互包含导致编译出错的问题,但是!!!!!如果头文件里的函数写了实现,重复包含的话仍然是要出错的,具体看问题2的解释
对于问题2:
如果在c.h中,有一个函数实现,比如:
int integer_add(const int a, const int b) { return a+b; }
在a.cpp和b.cpp中都包含的c.h,那么编译的时候:
a.cpp编译得到a.obj,b.cpp编译得到b.obj;
在链接时期,a.obj和b.obj和运行库连接起来生成可执行文件的时候,就会冲突,因为两个obj里都有一份integer_add的函数实现,导致链接器不知道对于调用者,应该使用哪一个副本
解决办法:
1.使用inline修饰函数
使用inline,意味着编译器会在调用此函数的地方把函数的目标代码直接插入,而不是放置一个真正的函数调用,也就是说这个函数实际上已经不再存在,而是像宏一样被就地展开了。
除了体积变大,使用inline还有这样的问题:inline严格来算不是关键字,inline是对编译器进行请求而不是强制,所以在一些特殊情况下,编译器并不会真正使用inline进行修饰
类函数在类定义的时候就实现的情况下,缺省就是inline的
模板函数也是相似的
2.使用static修饰函数
使用static意味着,所有包含此头文件的源文件中都会存在此函数的一份副本,代码也有一定膨胀,但是相互不冲突,因为static关键字保证了该函数可见度为单个源文件
通过static修饰类函数,就可以使用这样的调用方式:Integer::add(i,j);
对于virtual函数,它总是生成一份代码,即使你显式使用inline关键字修饰,因为:virtual函数地址会被写到类的v-table里,在运行期才被调用。
对于类被多个cpp包含的情况下,没有出现冲突,原因是遵守“单一定义规则”(One_Definition Rule, ODR) :如果对同一个类的两个定义完全相同且出现在不同编译单元,会被当作同一个定义
相关引用:
以上是关于重复定义问题的主要内容,如果未能解决你的问题,请参考以下文章