2010-03-12 34 views
24
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? 
+3

¿Realmente quiere usar herencia privada? –

+1

Alguien le agrega un terminador de enunciado. Cambio solo un carácter. –

Respuesta

38

No, no se puede acceder derived_int porque derived_int es parte de Derived, mientras basepointer es un puntero a Base.

Puede hacerlo al revés sin embargo:

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

Las clases derivadas heredan los miembros de la clase base, no al revés.

Sin embargo, si su basepointer estaba apuntando a una instancia de Derived entonces se podría acceder a él a través de un reparto:

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

Tenga en cuenta que tendrá que cambiar su herencia a public primera:

class Derived : public Base 
+1

¿no debería usar dynamic_cast en lugar de static_cast? –

+9

Eso depende de si él sabe o no que es un 'Derived' o no. Si está 100% seguro (como estamos aquí) entonces 'static_cast' está bien. –

+0

¿no significan todos que reinterpret_cast en lugar de static_cast? Estoy bastante seguro de que static_cast no compilará. – Balk

9

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 hacer eso 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 los puntos basepointer como algo más que una derivada, su programa morirán horriblemente, que es el resultado previsto.

Alternativamente, puede usar dynamic_cast (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 algunos sugieren, es una manera segura de dispararse en el pie. No contribuyas a la gran cantidad de historias de horror de "inseguridad de la familia del lenguaje C".

+0

"Alternativamente, puede usar dynamic_cast (basepointer). Pero necesita al menos una función virtual en la base para eso, y prepárese para encontrar un cero". -> Good Point Seva.Liked It :) – mahesh

+3

Usar 'static_cast' no es una forma de dispararte en el pie. Creo que lo estás confundiendo con la notación de lanzamiento explícita de C '(T) x'. 'static_cast' por otro lado es type safe, pero' dynamic_cast' devolverá un puntero nulo si no puede convertirse, mientras que 'static_cast' emitirá un error de compilación. – 0x499602D2

4

puede utilizar CRTP

que básicamente utiliza la clase derivada de la plantilla para la clase base

3

Es posible por dejar que la clase base conocen el tipo de clase derivada. Esto se puede hacer haciendo que la clase base sea una plantilla de tipo derivado. Esta expresión C++ se llama curiously recurring template pattern.

Conociendo la clase derivada, el puntero de la clase base se puede convertir estático en 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(); 
} 
0

// Si sabe lo que deriva la clase que se va a utilizar

Derivado * derivedpointer = dynamic_cast < Derivado *> basepointer;

// entonces puede acceder a la clase derivada utilizando derivada

Cuestiones relacionadas