为什么类的定义应当写在头文件中,从而被多个源文件包含?
比如myclass.h定义了一个类myclass(只定义类,不定义成员函数),
file1.cpp里#include "myclass.h",编译得到file1.obj;
file2.cpp里也#include "myclass.h",编译得到file2.obj;
那么把file1.obj和file2.obj(和运行库)连接起来生成可执行文件的时候,为什么不会有冲突呢?2个文件都包含了myclass类的定义。
以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等文件格式文档以及编译器源代码。