c++普通函数在头文件定义报重复定义的错误。而class定义不会

c++普通函数在头文件定义报重复定义的错误。而class定义不会

 

 

c++普通函数在头文件定义报重复定义的错误。而class定义不会

 

 

c++普通函数在头文件定义报重复定义的错误。而class定义不会

 

 

 

以上代码可以正常运行!

我们可能会赶到奇怪,为什么class C在header中定义了,并且在其他两个cpp中都include了,结果,链接时不会报重复定义的错误?

 

原因:

编译单元:一个.cc或.cpp作为一个编译单元.生成.o,简单来说一个cpp文件就是一个编译单元。

类的声明:

class A;  //类的声明

类的声明和普通变量声明一样,不产生目标代码,可以在同一、以及多个编译单元重复声明。

类的定义:

class A {

……

};  //类的定义

类的定义不产生目标代码,只是告诉编译器,类的数据格式是如何的,实例化后对象该占多大空间,它和普通变量的声明唯一的区别是不能在同一编译单元内出现多次。同一编译单元内,类重复定义,会编译时报错,因为编译器不知道在该编译单元中,实例化对象的时候该调用哪一个定义的类?但是在不同编译单元内,类可以重复定义,因为类的定义未产生实际代码。因为它具有内部链接,(所谓内部链接指的是该名称对于所在编译单元是局部的,在链接时不会与其他编译单元中同样 的名称产生命名冲突),所以类定义在头文件中在链接时候不会冲突。

 

函数头文件中定义多次include就报重复定义问题

先来做一个实验,你在一个头文件中定义一个类,然后把内中的一个函数的实现写在这个头文件当中。

//A_test.h

#ifndefine _A_TEST_

#define _A_TEST_

class A

{

void test();

};

void A::test()

{

}

#endif

//A_test.cpp

#include A_test.h

//B_test.cpp

#include A_test.h

//C_test.cpp

#include A_test.h

然后在两个B.cpp,C.cpp包含这个头文件,请问能否编译通过。答案是不行的,会报错,所你重复定义函数test()

但是如果你把这个函数定义到class A里面,然后编译就不报错了。

另外如果你把这个函数定义在这个头文件类的外面,但是前面加上inline,也可以通过编译。

除此之外,如果你把这个函数的实现写在另外一个包含这个头文件的cpp文件中,也可以通过编译,这也是最规范的写法。

 

与此对应,如果你在这个头文件中声明了一个函数,如果直接就在这个头文件中实现,那么除非你把它定义为inline 函数,不然会发生二次定义的错误,当然把一个实现放到一个对应的cpp中,自然不会报错。

在常规理解中,.h只能写声明,cpp写实现。这是很规范 。但是为什么有些库的头文件也把一些类的实现写出来了,有些函数也直接定义在那个头文件中,在很多.cpp中也不断的被包含呢,结果并不报错。举个例子来时,complex.h这个头文件在很多数值.cpp中间都要包含,如果这个头文件中有些函数写了实现,就会报错。

那么究竟如何来理解这种现象呢:

有3点:

1是编译器的唯一命名规则,就是inline函数,class和模板类函数被多次包含的情况下,在编译的时候,编译器会自动把他们认为是同一个函数,不会发生二次定义的问题。前提是他们一模一样。

2是编译器会把class里面定义的函数当做inline函数,所以直接在类里面实现函数的定义没有关系。由上面的说明,他不会发生二次定义的问题。

3一般函数的声明和实现分开,在编译的时候,声明可以无数次,但是定义只能一份,只会生成一份函数的.obj,所以有函数调用的地方,编译器必须在调用的地方先保持现场,然后在花点时间去调用函数,然后回来,恢复现场。所以函数在头文件中实现,如果被包含二次。函数的实现就被编译了2次,如果单独写在一个.cpp中间,自然就编译成为一份.obj,不会产生二义性的问题。

3.inline函数在编译的时候直接复制在有该函数的地方,在空间上有消耗,但是在省去了时间上的消耗,是一个模板函数。也就是说在有这些函数的地方都不需要去调用函数,也就不涉及有2种函数可以调用产生的二义性问题。

 

因此,complex.h这个头文件要被反复包含,要么把所有函数都放到类里面定义,要么全面写在外面,前面加上inline。

另外,模板类函数应该也是编译器特殊处理过

原文链接: https://www.cnblogs.com/wangshaowei/p/14194228.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    c++普通函数在头文件定义报重复定义的错误。而class定义不会

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/206548

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午10:36
下一篇 2023年2月12日 下午10:37

相关推荐