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