• ベストアンサー

ヘッダファイルの外側にメンバ関数を定義する時のinline指定について

main.cpp、DUT.cppを分割コンパイルした場合、リンク時に main.o(.text+0x0): In function `DUT::FuncA()': <省略>/DUT.h:12: multiple definition of `DUT::FuncA()' DUT.o(.text+0x0):<省略>/DUT.h:12: first defined here collect2: ld returned 1 exit status とエラーが出ます。FuncA関数をインライン指定するとリンクエラーはなくなります。 インライン指定しないと関数の実体がDUT.cpp/main.cppコンパイル毎に生成され、リンク時に衝突してしまう感覚はなんとなくわかるのですが、インライン指定時にFuncA関数の中身はどこに存在しているのでしょうか。 nm/objdumpで見ても見つかりません。 どういうメモリ構造故、インライン指定時には問題が起きていないのか、どこにFuncA関数の実体はあるのかを教えていただけないでしょうか。 // DUT.h #ifndef TLM_DUT_H #define TLM_DUT_H class DUT{ public: void FuncA() ; int ValB ; } ; inline // インライン指定しないとコンパイルエラー void DUT::FuncA(){ ... } #endif // DUT.cpp #include "DUT.h" // main.cpp #include "DUT.h" int main( int, char** ){ return 0; } % make g++ -g -Wall -c DUT.cpp g++ -g -Wall -c main.cpp g++ -g -Wall -o run.x DUT.o main.o 2>&1 | c++filt main.o(.text+0x0): In function `DUT::FuncA()': <省略>/DUT.h:12: multiple definition of `DUT::FuncA()' DUT.o(.text+0x0):<省略>/DUT.h:12: first defined here collect2: ld returned 1 exit status

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

inline指定子を付けた場合でも、関数はデフォルトでは外部結合になります。そして、インライン置換されなかったインライン関数(例えば、再帰呼出しを行ったり、インライン関数へのポインタを取得した場合)や、インライン関数の中で定義された静的記憶域期間を持つオブジェクトは、リンク時に一箇所にまとめられます。 実際にコンパイル結果を調べたり、リンク後にnmを使って関数が配置されたアドレスを調べれば分かります。

その他の回答 (3)

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.4

実際の挙動はコンパイラ次第でしょうけど、インライン関数で呼び出しがなければ完全になくなっていても不思議ではないですね。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

混乱するといけませんんで、念のため指摘しておきます。 #1の方が書かれている > static宣言された場合と同じくファイルスコープになるので の部分ですが、static指定子を付けた場合は内部結合になるのであって、ファイルスコープになるのではありません。 また、C++にはファイルスコープというのは存在しません。C++にあるのは、名前空間有効範囲であって、明示的にnamespaceで囲まれていない部分は、大域的名前空間有効範囲になります。

  • rinkun
  • ベストアンサー率44% (706/1571)
回答No.1

インライン指定というのは元々、関数を呼び出す部分に関数の中身を展開するように指定するものです。 従って、インライン指定したメンバ関数は、インライン指定が適用されれば、そのメンバ関数を呼び出している部分にそれぞれ展開されています。 ただしインライン指定は必ず適用されるとは保証されてません。関数が大きすぎる場合などインライン展開が効率的でない場合には展開されません。 しかしその場合でもインライン指定した関数はstatic宣言された場合と同じくファイルスコープになるので、リンク時に衝突することはありません。

cafe2cafe
質問者

お礼

回答ありがとうございます。 インライン・メンバ関数を呼び出しているメンバ関数に展開されるとの事ですが、質問内容に書いた記述の場合は、呼び出しているメンバ関数はいない事になるのですが、この場合は、(最適化等で)実体はなくなるのでしょうか。 nm/objdumpでインライン・メンバ関数が見当たらず。。

関連するQ&A

専門家に質問してみよう