据我所知,如果我在A.h
中定义非内联函数,并在A.h
和main.cpp
中包含A.cpp
。然后会出现功能重新定义错误。
示例代码如下:
A.H:
void hello(){}
A.cpp:
#include "A.h"
main.cpp中:
#include "A.h"
但是,如果我在A.h
中定义一个类,在A.h
和main.cpp
中包含A.cpp
,那么为什么没有类重新定义错误 }?
A.H:
class A{};
A.cpp:
#include "A.h"
main.cpp中:
#include "A.h"
以类似内联函数的方式处理类进程(我对内联函数进程的了解很少,但我听说内联函数有一些标记,编译器(或链接器?)将删除所有其他定义副本最后留下一个定义)?
答案 0 :(得分:4)
有两种方法可以回答这个问题。我们可以查看C ++标准以了解规则的含义,并且我们可以查看编译器的实际实现,以了解为什么在实践中会发生这种情况。
如果我们正在查看C ++标准,则会有一条称为One Definition Rule或ODR的规则。 ODR说类可以在多个翻译单元中定义,但定义必须相同(使用.h
文件可以很容易地保证这一点)。但非内联函数只能在单个翻译单元中定义。
如果我们查看编译器的实际实现,这种行为的原因很简单。类定义不会将任何内容输出到.o
文件中(除了某些调试信息之外)。另一方面,函数定义输出一些编译的目标代码以及符号表条目。
如果检查目标文件的内容,则可以看到此操作:
$ cat test.cc
class Foo {};
void hello() {}
$ g++ -c -o test.o test.cc
$ nm test.o
0000000000000000 T __Z5hellov
在test.cc
中我定义了一个类和一个函数。但是这个类没有向目标文件中发出任何东西,只有函数发生了。这就是为什么当两个.o
文件定义同一个类时没有冲突的原因。
内联函数需要特殊处理以避免导致链接错误。它们被放在称为COMDAT部分的特殊部分中。您可以阅读有关此here的更多信息。