头文件里面实现一个函数,在两个cpp中包含,则重复定义,如果加上inline则不会报错

为什么类的定义应当写在头文件中,从而被多个源文件包含?

比如myclass.h定义了一个类myclass(只定义类,不定义成员函数),
file1.cpp里#include "myclass.h",编译得到file1.obj;
file2.cpp里也#include "myclass.h",编译得到file2.obj;
那么把file1.obj和file2.obj(和运行库)连接起来生成可执行文件的时候,为什么不会有冲突呢?2个文件都包含了myclass类的定义。
因为这遵守“单一定义规则”(One-Definition Rule, ODR)。根据此规则,
如果对同一个类的两个定义完全相同且出现在不同编译单位,会被当作同一个定义。

这里头文件分别被两个不同的编译单位(file1.cpp, file2.cpp)包含,满足ODR规则,会被当作同一个定义。
所以不会有冲突。

此外,模板和inline函数也适用此规则。
以g++为例,类的代码出现在包含类方法定义的编译单元,引用他的编译单元会在链接时寻找类代码。如果.h中在类定义大括号内直接定义了函数,那么类代码会出现在每一个include这个.h的编译单元中。 以前者为例:
myclass.h:

class MyClass
{
    public:
        MyClass(int i);
        void add();
        int m;
};

myclass.cpp:

#include "myclass.h"
MyClass::MyClass(int i)
{
    this->m = i;
    add();
}
void MyClass::add()
{
    this->m ++;
}

file1.cpp:

#include "myclass.h"
void f1()
{
    MyClass mc(10);
}

file2.cpp:

#include "myclass.h"
void f2()
{
    MyClass mc(20);
}

main.cpp:
int main()
{
    void f1();
    void f2();
    f1();
    f2();
}

file1.o反汇编节选:
   0:    55                       push   %ebp
   1:    89 e5                    mov    %esp,%ebp
   3:    83 ec 28                 sub    $0x28,%esp
   6:    c7 44 24 04 0a 00 00     movl   $0xa,0x4(%esp)
   d:    00 
   e:    8d 45 f4                 lea    -0xc(%ebp),%eax
  11:    89 04 24                 mov    %eax,(%esp)
  14:    e8 fc ff ff ff           call   15 <_Z2f1v+0x15>
            15: R_386_PC32    _ZN7MyClassC1Ei

myclass.o反汇编节选:
0000001c <_ZN7MyClassC1Ei>:
  1c:    55                       push   %ebp
  1d:    89 e5                    mov    %esp,%ebp
  1f:    83 ec 18                 sub    $0x18,%esp
  22:    8b 45 08                 mov    0x8(%ebp),%eax
  25:    8b 55 0c                 mov    0xc(%ebp),%edx
  28:    89 10                    mov    %edx,(%eax)
  2a:    8b 45 08                 mov    0x8(%ebp),%eax
  2d:    89 04 24                 mov    %eax,(%esp)
  30:    e8 fc ff ff ff           call   31 <_ZN7MyClassC1Ei+0x15>
            31: R_386_PC32    _ZN7MyClass3addEv

可见类代码在myclass.o, file1.o在类定义的帮助下,通过_ZN7MyClassC1Ei引用类方法代码。 

其它细节可以反汇编代码、看elf/pe等文件格式文档以及编译器源代码。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值