ネストされたクラスを前方宣言してから、それを外部クラスの具象(ポインター/参照ではない)データメンバーの型として使用することはできますか?
I.E.
class Outer;
class Outer::MaybeThisWay // Error: Outer is undefined
{
};
class Outer
{
MaybeThisWay x;
class MaybeThatOtherWay;
MaybeThatOtherWay y; // Error: MaybeThatOtherWay is undefined
};
このようなネストされたクラスを前方宣言することはできません。
何をしようとしているかに応じて、外側のレイヤーでクラスではなく名前空間を使用できる場合があります。このようなクラスは問題なく転送宣言できます。
namespace Outer {
struct Inner;
};
Outer::Inner* sweets; // Outer::Inner is incomplete so
// I can only make a pointer to it
Outerが絶対にクラスである必要があり、名前空間に分類できない場合は、OuterがInnerを前方宣言するコンテキストで完全な型である必要があります。
class Outer
{
class Inner; // Inner forward-declared
}; // Outer is fully-defined now
Outer yes; // Outer is complete, you can make instances of it
Outer::Inner* fun; // Inner is incomplete, you can only make
// pointers/references to it
class Outer::Inner
{
}; // now Inner is fully-defined too
Outer::Inner win; // Now I can make instances of Inner too
含まれているクラスを完全に指定せずにネストされたクラスを前方宣言する方法はありません。この小さなトリックはちょっと問題を修正します
class Outer_Inner
{
};
class Outer
{
public:
typedef Outer_Inner Inner;
};
これは私の命名規則と同じように機能しますOuter_Inner
は有効なクラス名ではないため、ネストされたクラスを参照していることは明らかです。
次のように、ネストされたクラスをまだ転送宣言することはできません。
class Outer::Inner;
ただし、少なくとも次のようにして前方宣言できます。
class Outer_Inner;
Outer_Innerの外観が気に入らない場合は、入れ子になったクラスの命名規則を好みに合わせて採用できます。 Outer__Inner
、Outer_nested_Inner
など.
いいえ、でも何が悪いのですか
class Outer {
public: //or protected or private
class Inner {
};
private:
Inner foo;
};
私が何かを欠落していない限り、ここでは前方宣言は意味がありません(質問に多くの詳細が欠けているため、これは可能です)
クラスが前方宣言されている場合は、前方宣言された型のオブジェクトへの参照またはポインタのみを宣言できます。メンバーや関数へのアクセスなど、他のことはできません。
クラスが前方宣言されている場合(ただし、完全な定義はまだありません)、クラスへのポインターを宣言できるのは、コンパイラーがクラスのサイズ(およびそのフィールドの名前も)をまだ認識していないためです。またはメソッド)。
参照やポインタではなく、タイプMaybeThatOtherWay
の属性を宣言する場合、コンパイラは外部クラスのサイズを決定するためにクラスの完全な定義を知っている必要があります。したがって、ネストされたクラスであるかどうかにかかわらず、フォワード宣言とその種のフィールド宣言は使用できません。
関数のパラメーターまたは静的変数として型が必要な場合は、クライアント側で行うことができます。たとえば、外部からイベント通知を受信するには:
class Client {
public:
private:
static void gotIt(int event);
class Helper;
};
#include <outer.hpp>
class Client::Helper {
public:
static void fromOuter(Outer::Inner const& inner)
{
gotIt(inner.event());
}
};