cdsfiui 发表于 2017-02-18 10:02

.h中定义的函数有函数体,多个使用者就会有重复定义?

我做了一个很简单的实验,一个.h文件中一个class定义,有函数体代码,一个c风格函数,如下:

$cat testInline.h
#pragma once
class C{
public:
    void f(){}
};
void g(){}

然后有两个使用者:

$cat use01.cpp
#include"testInline.h"
void g01(){
    g();
    C obj1;
    obj1.f();
}


$cat use02.cpp
#include"testInline.h"
int main(){
    g();
    C obj2;
    obj2.f();
    return 0;
}


如果联合编译use01和use02来生成一个可执行文件,那么会有编译错误

$g++ use01.cpp use02.cpp
duplicate symbol __Z1gv in:
    /var/folders/zv/b953j0_55vldj97t0wz4qmkh0000gn/T/use01-34f300.o
    /var/folders/zv/b953j0_55vldj97t0wz4qmkh0000gn/T/use02-838e05.o
ld: 1 duplicate symbol for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

很奇怪:
我在头文件中已经有了#pragma once,都不能阻止这个所谓的重复定义(__Z1gv是全局函数g())

然后我在testInline.h当中把g()的定义修改成了
inline void g(){}

这样就好了! 不是说inline关键字没有什么用的吗,编译器会自行决定是否内敛一个函数呢?
而且,为什么class C的函数f有了函数体,不报重复定义的错误(也不需要加inline)。而g()这个函数会报重复定义的错误除非我加上inline呢?

希望我的问题表述清楚了,请解惑。

windoze 发表于 2017-02-18 10:16

所以你才需要inline

cdsfiui 发表于 2017-02-18 11:30

回复 2# windoze

为何C::f()不需要inline而::g()需要inline呢?

MMMIX 发表于 2017-02-18 14:16

回复 1# cdsfiui

1. #pragma once 是用来防止头文件在一个编译单元(源文件)中被重复包含的;
2. inline 当然是有用的啦,在不加优化选项的情况下,编译器未必会自动内联函数;

3. class C 中定义的 member function 默认就是内联的。

windoze 发表于 2017-02-19 21:24

回复 4# MMMIX

inline不光是优化选项,而且还标明该函数是weak symbol,允许多次出现在不同的compilation unit里。
页: [1]
查看完整版本: .h中定义的函数有函数体,多个使用者就会有重复定义?