web-dev-qa-db-ja.com

C ++ Accessの基本クラスポインターから派生したクラスメンバー

クラス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?
34
Peter

いいえ、アクセスできませんderived_intなぜならderived_intDerivedの一部であり、basepointerBaseへのポインターです。

ただし、逆の方法でも実行できます。

Derived* derivedpointer = new Derived;
derivedpointer->base_int; // You can access this just fine

派生クラスは基本クラスのメンバーを継承しますが、その逆は継承しません。

ただし、basepointerDerivedのインスタンスを指している場合は、キャストを介してアクセスできます。

Base* basepointer = new Derived;
static_cast<Derived*>(basepointer)->derived_int; // Can now access, because we have a derived pointer

最初に継承をpublicに変更する必要があることに注意してください。

class Derived : public Base
58
Peter Alexander

ここで地雷原で踊っています。基本クラスは、それが実際に派生のインスタンスであることを決して知ることができません。最も安全な方法は、ベースに仮想関数を導入することです。

_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;
_

basepointerDerived以外のものを指している場合、プログラムはひどく死にます。これは意図した結果です。

または、dynamic_cast<Derived>(basepointer)を使用できます。ただし、そのためにはBaseに少なくとも1つの仮想関数が必要であり、ゼロに遭遇する準備ができています。

_static_cast<>_は、いくつかの提案のように、自分を足で撃つ確実な方法です。 「C言語ファミリの安全でない」ホラーストーリーの膨大なキャッシュに貢献しないでください。

10
Seva Alekseyev

[〜#〜] crtp [〜#〜] を使用できます

基本的に、基本クラスのテンプレートで派生クラスを使用します

7
kirill_igum

基本クラスに派生クラスのタイプを知らせることで可能です。これは、基本クラスを派生型のテンプレートにすることで実行できます。この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();
}
4
Paweł Bylica

//使用する派生クラスがわかっている場合

Derived * derivedpointer = dynamic_cast <Derived *> basepointer;

//派生ポインタを使用して派生クラスにアクセスできます

0
Roger Wang