プライベートメンバーをヘッダーに配置する必要があるのはなぜですか?


62

プライベート変数は、クラスのユーザーに複雑さと実装の詳細を隠す方法です。これはかなり良い機能です。しかし、なぜc ++ではクラスのヘッダーに入れる必要があるのか​​理解できません。これには2つの厄介な欠点があります。

  • ユーザーからのヘッダーを乱雑にします
  • 内部が変更されるたびに、すべてのクライアントライブラリの再コンパイルを強制します

この要件の背後に概念的な理由はありますか?コンパイラの作業を簡単にするだけですか?


空の構造体をヘッダーで宣言できますが、使用する場合はそのような構造体へのポインタのみを使用できます(割り当てることはできません)
ラチェットフリーク

3
@ratchetfreak:いいえ、空(struct foo{};)は許可されていませんが、前方宣言(struct foo;)は許可されています。
–MSalters

@MSaltersそれは私が意味したものです
ラチェットフリーク

1
欠点を追加しましょう。* .hファイルにプライベート関数ヘッダーを書き込むことは、時間の無駄です。(しばらくの間友人のクラスを忘れて)
ジョニー

回答:


68

これは、C ++コンパイラがインスタンス化時に適切な量のメモリを割り当てるために、クラスの実際のサイズを知っている必要があるためです。また、サイズにはすべてのメンバーが含まれ、プライベートメンバーも含まれます。

これを回避する方法の1つは、ハーブサッターの週の達人シリーズ#24および#28で説明されているPimplイディオムを使用することです

更新

確かに、(より一般的に、ヘッダ/ソースファイルを区別し、この#includeS)はC ++での大きな障害である、日中C.戻るから継承されたC ++ Cを作成したところ、この、大規模なソフトウェア開発とは経験が、まだありませんでした本当の問題を引き起こし始めます。それから学んだ教訓は新しい言語の設計者に注意されましたが、C ++は後方互換性の要件に縛られているため、言語のこのような根本的な問題に対処することは非常に困難です。


この種の情報はクラスライブラリだけに含まれているのではないでしょうか?リンクに使用されていますか?
サイモンベルゴ

@サイモン、「クラスライブラリ」とはどういう意味ですか?
ペテルトレック

クラス定義とメソッドを含むオブジェクトファイルのコレクション
Simon Bergot

7
C ++が作成されたとき、AT&T / Bell Labs(当時のStroustrupsの雇用者)は確かに大規模なC開発の経験がありました。彼らの5ESS電話交換ソフトウェアは、当時、おそらく世界最大のシングルCプログラムでした。オブジェクト指向についての初期のアイデアは、そのコードベースで既に目に見えており、Cfrontはそれらの手法を模倣しました。ただし、の概念privateはより現代的です。
–MSalters

1
Cでは、ライブラリ関数にアロケーターを配置するだけでした。クライアントはそのような構造をまったく割り当てることができません。これによりオーバーヘッドが少し増えますが、バージョン間でコードを移行するのは簡単なので、多くの場合価値があります。ただし、C ++で見られるものとは非常に異なるコードスタイルになる傾向があります。
ドナルドフェローズ

15

クラスの定義は、クラスのオブジェクトを使用した場所にかかわらず、コンパイラがメモリ内で同一のレイアウトを生成するのに十分である必要があります。たとえば、次のようなものが与えられた場合:

class X { 
    int a;
public:
    int b;
};

コンパイラーは通常a、オフセット0およびbオフセットにあり4ます。コンパイラがこれを単なるものと見なした場合:

class X { 
public:
    int b;
};

これはb、オフセット4ではなくオフセット0にあるべきだと「考え」ます。その定義を使用するコードがに割り当てられている場合b、最初の定義を使用するコードaは変更されます。

クラスのプライベートな部分に変更を加えることによる影響を最小限に抑える通常の方法は、通常pimplイディオムと呼ばれます(これについてはGoogleが多くの情報を提供できると確信しています)。


1
私は設計上の決定について尋ねています。もちろん、言語が機能するためには、プライベートメンバー宣言をどこかに配置する必要があります。しかし、なぜもっとプライベートな場所ではなくヘッダーに置くべきなのでしょうか?
サイモンベルゴット

7
@Simon:ヘッダーは、クラス/構造体がどのように見えるかを伝えるためにコンパイラが見るすべてです。モジュールのようなものをC ++に追加するという議論がありましたが、これはその種のデータをもう少し隠しますが、今のところ承認されていません(完全に削除されたわけでもありません)。
ジェリーCo

3
それでも、些細なルールは、そのような「.cppで定義された」プライベートメンバーを最後に割り当てることです。つまり、パブリックメンバーと「通常の」プライベートメンバーのオフセットは、それらに依存しません。IMOの本当の理由は、そのようなクラスから継承できないことです。派生部分は、それらのプライベートメンバーにも従わなければならないからです。
-MSalters

3

いくつかの理由が考えられます。他のほとんどのクラスはプライベートメンバーにアクセスできませんが、フレンドクラスは引き続きアクセスできます。したがって、少なくともこの場合、ヘッダーで必要になる可能性があるため、フレンドクラスはそれらが存在することを確認できます。

依存ファイルの再コンパイルは、インクルード構造に依存する場合があります。別のヘッダーではなく.cppファイルに.hファイルを含めると、場合によっては再コンパイルの長いチェーンを防ぐことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.