クラスDerived
のオブジェクト(Base
の基本クラス)を割り当て、そのオブジェクトへのポインターを基本クラスを指す変数に格納する場合、どのようにアクセスできますかDerived
クラスのメンバー?
以下に例を示します。
class Base
{
public:
int base_int;
};
class Derived : public Base
{
public:
int derived_int;
};
Base* basepointer = new Derived();
basepointer-> //Access derived_int here, is it possible? If so, then how?
いいえ、アクセスできませんderived_int
なぜならderived_int
はDerived
の一部であり、basepointer
はBase
へのポインターです。
ただし、逆の方法でも実行できます。
Derived* derivedpointer = new Derived;
derivedpointer->base_int; // You can access this just fine
派生クラスは基本クラスのメンバーを継承しますが、その逆は継承しません。
ただし、basepointer
がDerived
のインスタンスを指している場合は、キャストを介してアクセスできます。
Base* basepointer = new Derived;
static_cast<Derived*>(basepointer)->derived_int; // Can now access, because we have a derived pointer
最初に継承をpublic
に変更する必要があることに注意してください。
class Derived : public Base
ここで地雷原で踊っています。基本クラスは、それが実際に派生のインスタンスであることを決して知ることができません。最も安全な方法は、ベースに仮想関数を導入することです。
_class Base
{
protected:
virtual int &GetInt()
{
//Die horribly
}
public:
int base_int;
};
class Derived : Base
{
int &GetInt()
{
return derived_int;
}
public:
int derived_int
};
basepointer->GetInt() = 0;
_
basepointer
がDerived
以外のものを指している場合、プログラムはひどく死にます。これは意図した結果です。
または、dynamic_cast<Derived>(basepointer)
を使用できます。ただし、そのためにはBase
に少なくとも1つの仮想関数が必要であり、ゼロに遭遇する準備ができています。
_static_cast<>
_は、いくつかの提案のように、自分を足で撃つ確実な方法です。 「C言語ファミリの安全でない」ホラーストーリーの膨大なキャッシュに貢献しないでください。
[〜#〜] crtp [〜#〜] を使用できます
基本的に、基本クラスのテンプレートで派生クラスを使用します
基本クラスに派生クラスのタイプを知らせることで可能です。これは、基本クラスを派生型のテンプレートにすることで実行できます。このC++のイディオムは 不思議な繰り返しテンプレートパターン と呼ばれます。
派生クラスを知っていると、基本クラスポインターを派生型へのポインターに静的にキャストできます。
template<typename DerivedT>
class Base
{
public:
int accessDerivedField()
{
auto derived = static_cast<DerivedT*>(this);
return derived->field;
}
};
class Derived : public Base<Derived>
{
public:
int field;
};
int main()
{
auto obj = new Derived;
obj->accessDerivedField();
}
//使用する派生クラスがわかっている場合
Derived * derivedpointer = dynamic_cast <Derived *> basepointer;
//派生ポインタを使用して派生クラスにアクセスできます