(環境: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";
}
main.cpp:
#include "foo.h"
int main()
{
foo();
}
Makefile:
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();
そして、それの複数の定義があります。1つはfoo1.cppにあり、もう1つは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.ofoo1.oとfoo2.oをリンクしてみます
$ make case3
error: multiple definition of 'foo()'
リンカは、foo1.oとfoo2.oでfooの2つの定義を検出するため、ランダムな定義を取得するのではなく、エラーで高速に失敗し、リンクしません。
質問
私の質問は次のとおりです。
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を返す必要があります。