函数定义在头文件中,被编译进两个.o 却能正常链接和执行?

2015-07-16 11:11:45 +08:00
 ilotuo
这是源码:

```
#ifndef __vtkOBJWriter_h
#define __vtkOBJWriter_h

class vtkOBJWriter : public vtkPolyDataAlgorithm
{
public:
//...
virtual int writeMtllib(std::ofstream &fout){};//这里被编译了两次(见编译警告),而且链接到同一个文件.但是没有报错..
void setMtl(string s){// 同上
mMtllibStr = s;
}
}

/**
int foo(){} //但是这个如果不注释的话不能编译.
*/

#endif
```

编译时,这个头文件被 main.cpp vtkOBJWriter.cxx include 却能编译.

[ 25%] Built target Non-Rigid-Registar


Scanning dependencies of target optimal_nonrigid_icp
[ 50%] Building CXX object src/optimal_nonrigid_icp/CMakeFiles/optimal_nonrigid_icp.dir/vtkOBJWriter.cxx.o
In file included from /Users/gerrie/repos/Non-Rigid-Registar/src/optimal_nonrigid_icp/vtkOBJWriter.cxx:29:
/Users/gerrie/repos/Non-Rigid-Registar/src/optimal_nonrigid_icp/vtkOBJWriter.hpp:57:48: warning: control reaches end of non-void function
[-Wreturn-type]
virtual int writeMtllib(std::ofstream &fout){}; //这里被编译了两次(见编译警告),而且链接到同一个文件.但是没有报错..
^
1 warning generated.
[ 75%] Building CXX object src/optimal_nonrigid_icp/CMakeFiles/optimal_nonrigid_icp.dir/main.cpp.o
In file included from /Users/gerrie/repos/Non-Rigid-Registar/src/optimal_nonrigid_icp/main.cpp:17:
/Users/gerrie/repos/Non-Rigid-Registar/src/optimal_nonrigid_icp/vtkOBJWriter.hpp:57:48: warning: control reaches end of non-void function
[-Wreturn-type]
virtual int writeMtllib(std::ofstream &fout){}; //这里被编译了两次(见编译警告),而且链接到同一个文件.但是没有报错..
^
1 warning generated.
Linking CXX executable ../../bin/optimal_nonrigid_icp
[100%] Built target optimal_nonrigid_icp


但是nm 显示只有一个.o正真包含这个符号:

O_O[11:03:07]release$ nm src/optimal_nonrigid_icp/CMakeFiles/optimal_nonrigid_icp.dir/vtkOBJWriter.cxx.o |grep writeMtllib
0000000000005a20 S __ZN12vtkOBJWriter11writeMtllibERNSt3__114basic_ofstreamIcNS0_11char_traitsIcEEEE
000000000000d680 S __ZN12vtkOBJWriter11writeMtllibERNSt3__114basic_ofstreamIcNS0_11char_traitsIcEEEE.eh
0000000000005ab0 S __ZN14myVtkOBJWriter11writeMtllibERNSt3__114basic_ofstreamIcNS0_11char_traitsIcEEEE
000000000000d700 S __ZN14myVtkOBJWriter11writeMtllibERNSt3__114basic_ofstreamIcNS0_11char_traitsIcEEEE.eh
^_^[11:03:16]release$ nm src/optimal_nonrigid_icp/CMakeFiles/optimal_nonrigid_icp.dir/main.cpp.o |grep writeMtllib
O_O[11:05:19]release$

这是怎么回事?所以是编译器自动优化,不编译第二个定义吗?
962 次点击
所在节点    C
3 条回复
hitmanx
2015-07-16 13:48:13 +08:00
按照c++标准,这不就是默认inline吗?
xylophone21
2015-07-16 13:54:24 +08:00
nm的时候加上 ”-CA"再贴一下。
dahakawang
2015-07-16 23:00:54 +08:00
放到头文件中定义的成员函数被include之后,在main.o和vtkOBJWriter.o中的确会有两个同名符号vtkOBJWriter::writeMtllib,但此种情况下,vtkOBJWriter::writeMtllib会被编译器置为weak symbol,所以后来linker看到两个同样的名字不会报错,只是随便选一个。

同样在头文件中被include的template实现也有类似的机制。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/206048

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX