subclase - C++ Accede al miembro de clase derivado del puntero de clase base
relaciones entre clases y objetos en java (5)
Si asigno un objeto de una clase Derived
(con una clase base de Base
) y almaceno un puntero a ese objeto en una variable que apunta a la clase base, ¿cómo puedo acceder a los miembros de la clase Derived
?
Aquí hay un ejemplo:
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?
// si sabes qué clase derivada vas a usar
Derivado * derivedpointer = dynamic_cast <Derived *> basepointer;
// entonces puedes acceder a la clase derivada usando derivedpointer
Es posible permitiendo que la clase base conozca el tipo de clase derivada. Esto se puede hacer haciendo que la clase base sea una plantilla de tipo derivado. Este modismo C ++ se llama CRTP .
Conociendo la clase derivada, el puntero de la clase base se puede convertir estático a un puntero al tipo derivado.
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();
}
Estás bailando en el campo minado aquí. La clase base nunca puede saber que en realidad es una instancia del derivado. La forma más segura de hacerlo sería introducir una función virtual en 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 el basepointer
señala como algo distinto a Derived
, tu programa morirá horriblemente, que es el resultado esperado.
Alternativamente, puede usar dynamic_cast<Derived>(basepointer)
. Pero necesita al menos una función virtual en la Base
para eso, y prepárese para encontrar un cero.
El static_cast<>
, como sugieren algunos, es una forma segura de dispararse en el pie. No contribuyas a la gran cantidad de historias de horror de "inseguridad de la familia del lenguaje C".
No, no puede acceder a derived_int
porque derived_int
es parte de Derived
, mientras que basepointer
es un puntero a Base
.
Puedes hacerlo al revés:
Derived* derivedpointer = new Derived;
derivedpointer->base_int; // You can access this just fine
Las clases derivadas heredan los miembros de la clase base, y no al revés.
Sin embargo, si su basepointer
apuntaba a una instancia de Derived
entonces podría acceder a ella a través de un elenco:
Base* basepointer = new Derived;
static_cast<Derived*>(basepointer)->derived_int; // Can now access, because we have a derived pointer
Tenga en cuenta que primero tendrá que cambiar su herencia a public
:
class Derived : public Base
puedes usar CRTP
básicamente usas la clase derivada en la plantilla para la clase base