(环境:gcc 4.6、c++11、glibc 2.13、binutils 2.21)
请考虑以下“链接”演示作为背景:
foo.h:
#pragma once
#include <iostream>
void foo();
foo1.cpp:
#include "foo.h"
void foo()
{
std::cout << "foo1";
}
foo2.cpp:
#include "foo.h"
void foo()
{
std::cout << "foo2";
}
主.cpp:
#include "foo.h"
int main()
{
foo();
}
生成文件:
compile: main.o foo1.o foo2.o
case1: compile
g++ -o case1.x main.o
case2: compile
g++ -o case2.x main.o foo1.cpp
case3: compile
g++ -o case3.x main.o foo1.o foo2.o
clean:
rm *.o *.x
我们有一个函数声明如下:
void foo();
我们对它有多个定义,一个在 foo1.cpp 中,一个在 foo2.cpp 中。
我们将 .cpp 文件编译成 .o 文件:
$ make compile
没问题,main.o、foo1.o 和 foo2.o 都生成了。
情况1
然后我们尝试链接 main.o:
$ make case1
error: undefined reference to 'foo()'
好的,main.o 引用了 foo 但没有链接定义。
案例2
现在我们尝试链接 main.o 和 foo1.o
$ make case2
在 foo1.o 中有一个 foo 的定义,所以它链接没有错误。
案例3
现在我们尝试链接 main.o foo1.o 和 foo2.o
$ make case3
error: multiple definition of 'foo()'
链接器在 foo1.o 和 foo2.o 中找到了 foo 的两个定义,因此它不是随机选择一个,而是快速失败并出现错误并且不链接。
问题
我的问题是:
是否可以将 foo1.cpp 的 foo 版本(可能带有某种 gcc 属性或编译指示)的定义标记为“弱”?具体意味着我希望案例 1 和案例 2 的行为保持不变,而案例 3 的行为更改为成功链接而没有警告或错误,并且 foo2.cpp 中的 foo 定义被链接(覆盖“弱”定义在 foo1.cpp 中)。
是否可以在运行时测试(并分配给布尔变量)是否链接了弱版本的 foo 或强版本(显然不执行函数)。即在main中实现一个函数,如下所示。
template<typename FunctionPtr> bool is_weak_linked(FunctionPtr fp);
is_weak_linked(foo) 应该在案例 2 中返回 true,在案例 3 中返回 false。