3

これの実際の違いは何ですか

//Foo.h
struct Foo {
  void bar() {
    //lots of complex statements
  }
};

この

//Foo.h
struct Foo {
  void bar();
};
//Foo.cpp
inline void Foo::bar() {
  //lots of complex statements
}

最終的にコンパイルされたプログラムでこれら2つのアプローチに違いはありますか、それとも同じであることが保証されていますか?

また、優れたコーディングの実践/経験の観点から、どちらを選択する必要があるか、およびその理由についてコメントしてください。「多くの複雑なステートメント」に注意してください。そのようなものが実際にヘッダーファイルにあるべき特定のケースはありますか? 私の知る限り、ブーストライブラリのほとんどはヘッダーのみです-なぜそれを選択したのですか?

4

2 に答える 2

8

最終的にコンパイルされたプログラムでこれら2つのアプローチに違いはありますか、それとも同じであることが保証されていますか?

どちらも同じです。
クラス/構造体本体内で定義されたメンバー関数は暗黙的にinline.
ただし、最初の例ではinline、このヘッダーが含まれるすべての翻訳単位で関数を d にすることができます。2 番目の例では、関数を定義する cpp ファイルでのみ関数をインライン化できます。これは、コンパイラが関数呼び出しの時点で関数の定義を確認して、インライン化を試みる必要があるためです。

コメントで Q に回答するには:

としてマークされた関数の定義を cpp ファイルに保持し、inlineこのA.cpp関数を別の cpp ファイルから呼び出そうとするとしますB.cpp「未定義の外部シンボル」エラーが発生します。これは、C および C++ では各翻訳単位が個別にコンパイルされ、コンパイル中に にある関数の定義がA.cpp利用できないためですB.cpp
関数が定義されている場所からのみ呼び出されるA.cpp場合、定義は同じファイルで利用可能であり、コンパイラとリンカーは喜んでコンパイルしてリンクします。

C++03 7.1.2 関数指定子:
パラ 3:

クラス定義内で定義された関数はインライン関数です。インライン指定子は、ブロック スコープの関数宣言には現れません。


優れたコーディング プラクティス/経験の観点から、どちらを選択する必要があり、その理由は何ですか?

クラス定義は、クラスのユーザーへのインターフェースとして機能します。このインターフェースのユーザーは、関数の実装の詳細を確認する必要はありません。彼らが見る必要があるのは、このインターフェイスの使用方法だけです。関数定義(あなたが言及したようにかなり長いもの)をクラス内に配置することにより、ユーザーに不必要な詳細を提供し、実際に見る必要があるものをユーザーが見るのを難しくします.
これを行う最善の方法は次のとおりです。

  • inlineキーワード &なしでクラス定義で関数を宣言します
  • キーワード付きの関数定義をinlineクラス本体の外に置きます。

よく読んでください:
クラス外で定義されたインライン メンバー関数では、インライン キーワードをクラス本体内の宣言の隣に配置するのが最適ですか?それともクラス本体外の定義の隣に配置するのですか?


私の知る限り、ブーストライブラリのほとんどはヘッダーのみです-なぜそれを選択したのですか?

Boost ライブラリのほとんどはテンプレート ライブラリであり、テンプレート ベースのライブラリの場合、コンパイラは使用時に定義を確認する必要があるため、テンプレート関数をインラインにする必要があります。
よく読んでください:
テンプレートをヘッダー ファイルにしか実装できないのはなぜですか?

于 2013-02-10T12:34:11.897 に答える
2

その機能性に関しては、これら2つは同等です。Foo.cppただし、後者はファイルにインラインでのみ可能です。

于 2013-02-10T12:38:15.773 に答える