Jok*_*_vD 8 c++ linker templates
想象一下,我们有三个.h文件:
f.h:
template <typename T> class Class {public: Class() {} T id(T x) { return x; }};
Run Code Online (Sandbox Code Playgroud)
g.h:
template <typename T> class Class {public: Class() {} T id(T x) { return x + 100; }};
Run Code Online (Sandbox Code Playgroud)
h.h:
template <typename T> class Class {public: Class(); T id(T x); };
Run Code Online (Sandbox Code Playgroud)
现在,我们还有三个.cpp文件:
f.cpp:
#include "f.h"
int f(int x) { Class<int> t; return t.id(x); }
Run Code Online (Sandbox Code Playgroud)
g.cpp:
#include "g.h"
int g(int x) { Class<int> t; return t.id(x); }
Run Code Online (Sandbox Code Playgroud)
h.cpp:
#include "h.h"
int h(int x) { Class<int> t; return t.id(x); }
Run Code Online (Sandbox Code Playgroud)
编译它们给了我们f.o,g.o和h.o.现在让我们抛出这个main.cpp:
#include <stdio>
extern int f(int);
extern int g(int);
extern int h(int);
int main() {
std::cout << f(1) << std::endl;
std::cout << g(2) << std::endl;
std::cout << h(3) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
啊 - 让我们做g++ main.cpp f.o g.o h.o.现在出乎我的意料:由于这三个.o文件包含三个不同的定义int Class<int>::id(int),我希望得到一个链接错误.但是,我得到的是一个工作a.out,打印1 2 3.如果我.o在命令中重新排序文件,它将打印101 102 103.
现在对于实际问题:链接器在这种情况下如何执行链接?它如何确定Class<int>要保留的实例和要丢弃的内容?为什么它不抱怨多个定义?
nm实用程序提供以下输出nm f.o g.o h.o:
f.o:
00000000 b .bss
00000000 d .data
00000000 t .text
00000000 t .text$_ZN5ClassIiE2idEi
00000000 t .text$_ZN5ClassIiEC1Ev
00000000 T __Z1fi
00000000 T __ZN5ClassIiE2idEi
00000000 T __ZN5ClassIiEC1Ev
g.o:
00000000 b .bss
00000000 d .data
00000000 t .text
00000000 t .text$_ZN5ClassIiE2idEi
00000000 t .text$_ZN5ClassIiEC1Ev
00000000 T __Z1gi
00000000 T __ZN5ClassIiE2idEi
00000000 T __ZN5ClassIiEC1Ev
h.o:
00000000 b .bss
00000000 d .data
00000000 d .eh_frame
00000000 t .text
00000000 T __Z1hi
U __ZN5ClassIiE2idEi
U __ZN5ClassIiEC1Ev
Run Code Online (Sandbox Code Playgroud)
显然,f.o和g.o两个出口标志__ZN5ClassIiE2idEi,以及h.o进口该符号(大写字母的意思是外部链接).它不会导致任何错误.为什么?
这个问题实际上是众所周知的:您违反了 ODR。由于模板的性质,编译器和链接器不会注意到这一点。发生的情况如下:
链接器假定ODR 尚未被违反,因此可以自由使用模板的任何实例化(即,具有相同参数的模板的所有实例化都会生成完全相同的代码)。只要您不违反 ODR,该系统就有意义。
现在,在您的情况下,链接器选择使用它获得的第一个实例化,这导致结果取决于链接的顺序。
| 归档时间: |
|
| 查看次数: |
233 次 |
| 最近记录: |