クラスが作成される前でもオブジェクトを宣言する
-
02-07-2019 - |
質問
C++ でクラスを作成する前にクラスのオブジェクトを宣言する方法はありますか?2 つのクラスを使用しようとしているので質問します。最初のクラスにはその中に 2 番目のクラスのインスタンスが必要ですが、2 番目のクラスには最初のクラスのインスタンスも含まれています。無限ループに陥るのではないかと思われるかもしれませんが、実際には、最初のクラスの前に 2 番目のクラスのインスタンスを作成する必要があります。
解決
次のようなことはできません。
class A {
B b;
};
class B {
A a;
};
最も明白な問題は、クラス B のサイズは A のサイズに依存するため、コンパイラーがクラス A を作成するために必要なサイズを知らないことです。
ただし、次のようにすることもできます。
class B; // this is a "forward declaration"
class A {
B *b;
};
class B {
A a;
};
クラス B を前方宣言として宣言すると、クラス定義全体をまだ持たなくても、そのクラスへのポインター (および参照) を使用できるようになります。
他のヒント
未定義のクラスのインスタンスを宣言することはできませんが、 ポインタ 1 つに:
class A; // Declare that we have a class A without defining it yet.
class B
{
public:
A *itemA;
};
class A
{
public:
B *itemB;
};
あるよ エレガントなソリューション テンプレートを使用して。
template< int T > class BaseTemplate {}; typedef BaseTemplate< 0 > A; typedef BaseTemplate< 1 > B; // A template<> class BaseTemplate< 0 > { public: BaseTemplate() {} // A constructor B getB(); } // B template<> class BaseTemplate< 1 > { public: BaseTemplate() {} // B constructor A getA(); } inline B A::getB() { return A(); } inline A B::getA() { return B(); }
このコードは機能します!それで、なぜそれが機能するのですか?その理由は、テンプレートのコンパイル方法に関係しています。テンプレートは、どこかでテンプレートを実際に使用するまで、関数署名の作成を遅らせます。これは、geta()もgetB()も、クラスAとBの両方がすでに完全に宣言されるまで分析されないことを意味します。それがこの方法の魔法です。
これはあなたが望むものに近いですか:最初のクラスには 2 番目のクラスが含まれていますが、(最初に作成される) 2 番目のクラスには最初のクラスへの参照しかありませんか?
これを相互参照と呼びます。見る ここ 例。