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?
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
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".
vous pouvez utiliser _ CRTP
vous utilisez essentiellement la classe dérivée dans le modèle pour la classe de base
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();
}
// 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