ProgrammingC++バックエンド開発者

C++では、クラスメンバー関数の宣言と定義にはどのようなアプローチがありますか?クラス内での宣言、クラス内での定義、およびクラス外での定義はどう異なりますか?これがインライン実装にどのように影響しますか?

Hintsage AIアシスタントで面接を突破

答え。

C++では、クラスメンバー関数を以下のように宣言できます:

  • クラス内で(インライン定義):

    class A { void foo() { /* ... */ } // クラス内で直接 };

    このような関数は暗黙的に inline と見なされます。

  • クラス内で(宣言のみ):

    class A { void foo(); // 宣言のみ }; void A::foo() { /* ... */ } // クラス外での定義

違い:

  • クラス内での定義(「その場で」)は自動的に inline を想定し、コンパイラはその関数を呼び出しのコードに埋め込むことができます。
  • クラス外での定義は 自動的には inline とはならず、明示的に指定する必要があります(inline)。これは以下のように追加できます:
    inline void A::foo() { /* ... */ }
  • クラス外での宣言は、定義が分離される場合に必要です。たとえば、コンパイルを迅速化し、インターフェースと実装を分離するために .cpp ファイルで行います。

アプローチの利点と欠点:

  • クラス内での定義は、小規模で頻繁に呼び出される関数に便利です。
  • 大きなメソッドや個別に変更されるメソッドの場合、クラス内では宣言のみを行い、定義は .cpp で行うのが効率的です。

騙しの質問。

クラス内で定義された関数は、必ずコンパイラによって実際にインライン化されるのでしょうか?

答え:いいえ。 inline というキーワード(クラス内での暗黙的な割り当てを含む)は、コンパイラへの単なる提案です。コンパイラは、その関数をインライン化することがあまりにも複雑または不適切と見なした場合、この提案を無視することがあります。


このトピックの詳細を知らないことで実際に起きたエラーの例。


物語 1

大規模プロジェクトで、クラスメンバー関数がヘッダーファイル内で inline として定義され、何千もの翻訳単位に含まれた結果、コンパイル時間が数倍に増加し、コードの重複によりバイナリが増大しました — コンパイラは常に同一の機械実装を統合するわけではありません。


物語 2

実行速度を向上させるために、開発者はクラスの全ロジックを宣言に移しました(.hファイル)。これにより、関数が変更される度にプロジェクト全体が再コンパイルされ、実際に統合が影響を受けるファイルのみが影響を受けるわけではありませんでした。


物語 3

チームの新しいメンバーが、テンプレートクラスの宣言に長いシリアライズメソッドとファイル操作メソッドを直接置いたため、エラーがすべてのTUにわたって偶発的に拡散し、実行ファイルのサイズが増大しながらパフォーマンスの向上が見られませんでした。