web-dev-qa-db-fra.com

Membre de la classe dérivée d'accès C++ à partir du pointeur de la classe de base

Si j'alloue un objet d'une classe Derived (avec une classe de base Base) et que je stocke un pointeur sur cet objet dans une variable pointant vers la classe de base, comment puis-je accéder aux membres de la classe Derived

Voici un exemple:

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?
28
Peter

Non, vous ne pouvez pas accéder à derived_int car derived_int fait partie de Derived, alors que basepointer est un pointeur sur Base.

Vous pouvez faire l'inverse si:

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

Les classes dérivées héritent des membres de la classe de base, et non l'inverse.

Toutefois, si votre basepointer pointait vers une instance de Derived, vous pouvez y accéder via un casting:

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

Notez que vous devez d'abord modifier votre héritage en public:

class Derived : public Base
49
Peter Alexander

Vous dansez sur le champ de mines ici. La classe de base ne peut jamais savoir qu’elle est en réalité une instance de la dérivée. Le moyen le plus sûr de le faire serait d'introduire une fonction virtuelle dans la 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;

Si basepointer indique autre chose qu'une Derived, votre programme mourra horriblement, ce qui correspond au résultat souhaité.

Alternativement, vous pouvez utiliser dynamic_cast<Derived>(basepointer). Mais pour cela, vous avez besoin d’au moins une fonction virtuelle dans la variable Base et soyez prêt à rencontrer un zéro.

Comme certains le suggèrent, le static_cast<> est un moyen sûr de se tirer une balle dans le pied. Ne contribuez pas à la vaste cache d'histoires d'horreur "manque de sécurité de la famille du langage C".

10
Seva Alekseyev

vous pouvez utiliser _ CRTP

vous utilisez essentiellement la classe dérivée dans le modèle pour la classe de base

6
kirill_igum

Il est possible en laissant la classe de base connaître le type de classe dérivée. Cela peut être fait en faisant de la classe de base un gabarit de type dérivé. Cet idiome C++ est appelé modèle de modèle curieusement récurrent .

Connaissant la classe dérivée, le pointeur de la classe de base peut être converti de manière statique en un pointeur sur un type dérivé.

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

// si vous savez quelle classe dérivée vous allez utiliser

Dérivé * dérivépointer = dynamic_cast <Dérivé *> basepointer;

// alors vous pouvez accéder à la classe dérivée en utilisant DerivePointer

0
Roger Wang