web-dev-qa-db-ja.com

クラス自体と同じ型のメンバーを持つクラスの「不完全な型」

私は同じクラスのプライベートメンバーを持つべきクラスを持っています:

class A {
    private:
        A member;
}

ただし、me​​mberは不完全な型であることがわかります。どうして?ポインターを使用する場合、不完全な型を教えてくれませんが、ポインターを使用したくないです。どんな助けでも大歓迎です

36
Sterling

メンバーを宣言するとき、あなたはまだ定義Aクラスなので、タイプAは未定義のままです。

ただし、A*、コンパイラはAがクラス名を表していることをすでに知っているため、「Aへのポインタ」のタイプはdefinedです。そのため、定義している型へのポインタを埋め込むことができます。

同じロジックが他のタイプにも適用されるため、次のように記述した場合:

class Foo;

クラスFooを宣言しますが、定義することはありません。あなたは書ける:

Foo* foo;

だがしかし:

Foo foo;

一方、コンパイラが再帰的な定義を許可した場合、タイプAにどのようなメモリ構造を期待しますか?

ただし、同じタイプの別のインスタンスを何らかの形で参照するタイプを持つことが論理的に有効な場合があります。人々は通常、それ以上のポインターを使用します:スマートポインター(boost::shared_ptr)手動で削除する必要がないようにします。

何かのようなもの:

class A
{
  private:
    boost::shared_ptr<A> member;
};
40
ereOn

これはあなたが達成しようとしていることの実例です:

class A {
public:
    A() : a(new A()) {}
    ~A() { delete a; a = nullptr; }
private:
    A* a;
};

A a;

ハッピースタックオーバーフロー!

26
Nick

Aは、その定義の終わりまで「不完全」です(ただし、これにはメンバー関数の本体は含まれません)。

この理由の1つは、定義が終了するまで、Aの大きさを知る方法がないことです(これは、メンバーのサイズの合計に加えて、他のいくつかのものに依存します)。あなたのコードはその良い例です。あなたのタイプAはタイプAのサイズによって定義されます。

明らかに、タイプAのオブジェクトには、タイプAのメンバーオブジェクトを含めることはできません。

ポインタまたは参照を保存する必要があります。どちらかを保存したいのではないかと思われます。

A内にAを含めることはできません。それを行うことができ、たとえば、A a;、次を参照する必要がありますa.member.member.member...無限に。それほど多くのRAMを利用できません。

2
mah

class Aのインスタンスにclass Aの別のインスタンスを含めるにはどうすればよいですか?

必要に応じて、Aへのポインターを保持できます。

1
Andrei

このタイプのエラーは、まだ完全に定義されていないクラスを使用しようとすると発生します。

代わりにA* memberを使用してみてください。

1
trema

クラスAが不完全である理由を理解する簡単な方法は、コンパイラーの観点から見てみることです。

とりわけ、コンパイラはAオブジェクトのサイズを計算できなければなりません。サイズを知ることは、自動メモリ内のスペースの割り当て、演算子newの呼び出し、sizeof(A)の評価など、多​​くのコンテキストで現れる非常に基本的な要件です。ただし、Aのサイズを計算するには、Aaのメンバーであるため、Aのサイズを知る必要があります。これは無限再帰につながります。

この問題に対処するコンパイラの方法は、その定義が完全に知られるまでAが不完全であると考えることです。不完全なクラスへのポインターと参照を宣言することはできますが、値を宣言することはできません。

0
dasblinkenlight

この問題は、コンパイラがコード内のAのオブジェクトに遭遇したときに発生します。コンパイラーは手をこすり、Aのオブジェクトを作成します。その間、Aには再びタイプAのメンバーがあることがわかります。したがって、Aのインスタンス化を完了するには、別のAをインスタンス化し、そうすることで、別のAなどをインスタンス化する必要があります。無限に再帰することになります。したがって、これは許可されていません。コンパイラは、クラスのオブジェクトのインスタンス化を開始する前に、すべてのメンバーのすべての型とメモリ要件を確認します。

0
Sushovan