質問

私が理解しているように、pimplイディオムは、C ++がすべてのプライベートクラスメンバーをヘッダーに配置するように強制するためにのみ存在します。理論的には、ヘッダーにパブリックインターフェイスのみが含まれる場合、クラスの実装を変更しても、プログラムの残りの部分を再コンパイルする必要はありません。

知りたいのは、C ++がそのような便利さを実現するように設計されていない理由です。クラスのプライベートな部分をヘッダーにオープンに表示する必要があるのはなぜですか(しゃれは意図していません)

役に立ちましたか?

解決

これはオブジェクトのサイズに関係しています。 hファイルは、とりわけ、オブジェクトのサイズを決定するために使用されます。プライベートメンバーが指定されていない場合、新しいオブジェクトの大きさがわかりません。

ただし、次の方法で目的の動作をシミュレートできます。

class MyClass
{
public:
   // public stuff

private:
#include "MyClassPrivate.h"
};

これは動作を強制しませんが、.hファイルからプライベートなものを取得します。 マイナス面として、これは維持する別のファイルを追加します。 また、Visual Studioでは、プライベートメンバーに対してインテリセンスが機能しません。これはプラスまたはマイナスの可能性があります。

他のヒント

ここには混乱があると思います。問題はヘッダーに関するものではありません。ヘッダーは何もしません(複数のソースコードファイルに共通のソーステキストを含める方法にすぎません)。

問題は1つありますが、C ++のクラス宣言では、インスタンスが機能するために必要なパブリックとプライベートのすべてを定義する必要があるということです。 (Javaについても同じことが言えますが、外部でコンパイルされたクラスへの参照が機能する方法により、共有ヘッダーなどを使用する必要がなくなります。)

(C ++だけでなく)一般的なオブジェクト指向技術の性質上、誰かが使用する具体的なクラスと、コンストラクタを使用して実装を配信する方法を知っている必要があります。公共部分。 (3、下)のデバイスは非表示にします。 (1)のプラクティスは、(3)を行うかどうかに関係なく、懸念を分離します。

  1. パブリックメソッド、主にメソッドのみを定義する抽象クラスを使用し、実装クラスにその抽象クラスを継承させます。したがって、ヘッダーの通常の規則を使用すると、abstract.hppが共有されます。また、継承されたクラスを宣言し、実装のメソッドを実装するモジュールにのみ渡されるimplementation.hppもあります。 implementation.hppファイルには、#include" abstract.hpp"が含まれます。クラス宣言で使用するため、抽象化されたインターフェイスの宣言のための単一のメンテナンスポイントがあるように、クラス宣言で使用します。

  2. 今、実装クラス宣言の非表示を強制する場合は、特定の完全なクラス宣言を所有せずに、具体的なインスタンスの構築を要求する何らかの方法が必要です。newは使用できません。ローカルインスタンスを使用できません。 (ただし、削除することはできます。)ヘルパー関数(クラスインスタンスへの参照を提供する他のクラスのメソッドを含む)の導入が代用です。

  3. 抽象クラス/インターフェースの共有定義として使用されるヘッダーファイルとともに、またはヘッダーファイルの一部として、外部ヘルパー関数の関数シグネチャを含めます。これらの関数は、特定のクラス実装の一部であるモジュールに実装する必要があります(したがって、完全なクラス宣言が表示され、コンストラクターを実行できます)。ヘルパー関数のシグニチャーはおそらくコンストラクターのシグニチャーに似ていますが、結果としてインスタンス参照を返します(このコンストラクタープロキシはNULLポインターを返すことができ、そのようなことが好きな場合は例外をスローすることもできます)。ヘルパー関数は、特定の実装インスタンスを構築し、抽象クラスのインスタンスへの参照としてキャストして返します。

ミッションが完了しました。

ああ、再コンパイルと再リンクは希望どおりに機能するはずです。実装のみが変更された場合に呼び出しモジュールの再コンパイルを回避します(呼び出しモジュールは実装にストレージ割り当てを行わないため)。

質問のポイントをすべて無視している-

開発者がPIMPLコードを入力する必要があるのはなぜですか?

私にとって、私が思いつく最良の答えは、それを操作できるC ++コードを表現する良い方法がないということです。たとえば、コンパイル時(またはプリプロセッサなど)のリフレクションまたはコードDOM。

C ++では、開発者がメタプログラミングを行うために、これらのいずれかまたは両方を使用できるようにする必要があります。

次に、パブリックMyClass.hに次のように記述できます。

#pragma pimpl(MyClass_private.hpp)

そして、独自の非常に簡単なラッパージェネレータを作成します。

誰かは私よりもはるかに冗長な答えを持っていますが、クイックレスポンスは2つあります。コンパイラは、ストレージスペース要件を決定するために構造体のすべてのメンバーを知る必要があり、コンパイラはこれらのメンバーは、決定論的な方法でオフセットを生成します。

この言語はすでにかなり複雑です。構造化データの定義をコード全体に分割するメカニズムは、ちょっとした災難になると思います。

通常、ポリシークラスは、ピンプルマナー。ポリシーパターンを使用することにはいくつかの追加の利点があると思います-実装の交換が簡単で、複数の部分的な実装を単一のユニットに簡単に組み合わせて、実装コードを機能的な再利用可能なユニットなどに分割できます

インスタンスを値で渡すとき、他のクラスに集約するときなどにクラスのサイズが必要なためでしょうか?

C ++が値のセマンティクスをサポートしていなかった場合は問題ありませんでしたが、サポートしています。

はい、しかし...

Stroustrupの「C ++の設計と進化」を読む必要があります。本。 C ++の取り込みを阻害していたでしょう。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top