下記の "void func"は、両方とも実体を持っているのか?
下記のコードをコンパイル&リンクしたところ、エラーがでずにコンパイラを通りました。
C++
1//header.hpp 2inline void func(); 3 4//sub.cpp 5#include"header.hpp" 6void func(){ 7 std::cout << “sub” << std::endl; 8} 9 10//main.cpp 11#include"header.hpp" 12void func(){ 13 std::cout << “main” << std::endl; 14} 15 16int main(){ 17 func(); 18 return 0; 19}
しかし、見てわかるように “void func”が2回定義されています。しかしエラーは出ませんでした。
試しに上記に書いてあるコード(.exe)を実行すると、mainの方の"void func(std::cout << main)"が実行され、subの方の"void func"(std::cout << sub) が実行されることはありませんでした。
ただ、”void func”をinlineでないようにすると、リンクエラーが起こりました。
↓下記は、同じようにコンパイルを通ったコードです。
- headerの inline を消去し、mainの "void func" に inline を付ける。
- headerの inline を消去し、subの "void func" に inline を付ける。
- headerのinlineを消去し、main, sub ともに inline を付ける。
いずれも、mainの方の "void func" のみ実行されました。
また、ファイルスコープなどの問題かもしれないと考え、「sub.cppから "void func" を呼び出す void func2関数を作成し、main関数で呼び出した」のですが、func2関数も変わらず、subの方の "void func" ではなく、mainの方の "void func" を呼び出しました。
反対に、以下の場合はエラーになりました。
- 関数の定義を同じソースコードに2種類書く(両方ともinline指定・片方のみにinline指定共にエラー) 。
質問内容
これらのコードを踏まえて、質問は以下の通りです。
0. "void func" は main.cpp の方のみ実体を持っているのか? それとも main.cpp も sub.cpp も共に実体を持っているが、何らかの事情で main.cpp の方しか使われないのか?
0. sub.cpp の "void func" が使われずに、main.cpp のほうが使われるのはなぜか?
0. なぜ上記のようなコードでも、リンクエラーにならずに、コンパイルを通るのか?(下記の「質問者の知識の程度」に記述したように、コンパイラが調整してくれるから? その調整の結果として、例えばsubの "void func" を無効化するなどしている?)
質問者の知識の程度
初心者です。私が持っている知識は、以下の通りです。
0. inline指定をすると、その関数はinline関数になる。
0. inline関数にすると、コンパイル時に関数の内容がコードに展開される(埋め込まれる)。
0. inline指定は、コンパイラの判断によって展開の可否が決まる。また、inline指定をしていなくても、コンパイラが最適化の結果として、勝手にinline展開されることがある(※コンパイラの設定次第で変更可能)。
0. inline関数はヘッダに記述することができる。その際、ODR(単一定義規則)違反にあたらないのは、inline関数の場合はコンパイラが調整してくれるため。
0. inline関数の定義をヘッダファイルに記述するのは、inline関数の処理を展開することに関係がある。ヘッダファイルに定義を記述しないと、どういう実体をソースコードに展開すればいいのかわからないから(ソースファイル1つで完結する場合は別)。
0. ODR違反とは、関数定義の実体が2つ以上あることで、どちらの実体を使えばいいのかわからない&実体の位置が確定しないために、問題になる。
もし知識が誤っている、正確性に問題がある場合は、ついでに正していただけると幸いです。
質問者の開発環境
- Windows 10
- Visual Studio Code
- Developer Command Prompt for VS 2019
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/11/25 12:49 編集
2021/11/25 13:50
2021/11/25 13:51
2021/11/25 13:52
2021/11/25 17:25
2021/11/25 23:27