2010-06-28 24 views
5

Aquí es lo que estoy tratando de hacer (este código no funciona):¿Cómo se puede clonar una clase C++ derivada a través de un puntero base?

class Base 
{ 
    virtual Base *clone() { return new Base(this); } 
    virtual void ID() { printf("BASE"); 
}; 

class Derived : publc Base 
{ 
    virtual Base *clone() { return new Derived(this); } 
    virtual void ID() { printf("DERIVED"); } 
} 

. 
. 
Derived d; 
Base *bp = &d; 
Base *bp2 = bp->clone(); 

bp2->ID(); 

lo que había como es ver "derivados" impreso ... lo que consigo es "el punto ". Soy un programador de C desde hace mucho tiempo, y tengo bastante experiencia con C++ ... pero no estoy progresando con esto ... cualquier ayuda sería apreciada.

+0

Mostrando más código, específicamente todos los constructores de cada clase en este caso son importantes. (Algunos se pueden deducir de su código, pero ayuda a obtener más respuestas correctas de todos ...) – Macke

+0

Hm. El código inicial tenía Base bp = & d. Ahora se ha cambiado a Base * bp = & d; – Macke

+0

No es relevante para la pregunta, pero también querrás destructores virtuales en las clases. –

Respuesta

0

Eres slicing la clase en Base bp = &d; (esto construye una nueva base de pares de bases desde el PTR-derivada.)

Trate Base* bp = &d; lugar. (Es decir, crear un puntero del tipo de base al objeto derivado.)

+1

No veo una instrucción de edición en el OP (en este momento), y el código ya está haciendo lo que sugiere (aunque no compila en absoluto). Si bien el problema informado ciertamente apesta a un problema de división, el código publicado no lo demuestra ... Editar: Vaya, estaba buscando una publicación incorrecta para la marca de edición. Tienes razón, Marcus. Lo siento por la molestia. –

1

Con Base bp = &d;

Usted ha "extraídos" d, por lo que el compilador, bp realmente sólo es de tipo Base, por lo que cuando se llame al bp->clone() el compilador llama a Base::clone(); y bp2->ID() imprime BASE.

Base& bp = d; hará lo que quiera.

0

Su ejemplo es incorrecto y no se compilará. Específicamente esta línea:

Base bp = &d; 

que también pueden ser la causa de su problema (que puede estar cortando su objeto), pero no puedo decir con certeza sin ver el código de trabajo.

También tiene un problema en sus dos clases no están relacionados (qué significa escribir class Derived : public Base?)

+0

Sí, sé que este código no se compilará. Solucioné este error en un minuto después de publicarlo, pero ustedes son rápidos. Consulte la pregunta corregida. No sé qué es "cortar", pero lo estoy buscando ... – wanlessv

+1

@wanlessv - siempre debe asegurarse de que su código compila antes de publicar una pregunta. Sin saber exactamente lo que intenta hacer, no siempre podemos ver cuál es el problema. –

3

Ese código está plagado de errores sintácticos. Quizás lo más significativo es que Derived no hereda de Base. En segundo lugar, aparte de los errores sintácticos (probablemente errores tipográficos simples), Base obviamente necesita un destructor virtual. El método de clonación prácticamente exige que se pueda llamar al operador delete en un puntero base (Base *).

class Base 
{ 
public: 
    virtual ~Base() {} 
    virtual Base* clone() const { return new Base(*this); } 
    virtual void ID() const { printf("BASE"); } 
}; 

class Derived: public Base 
{ 
public: 
    // [Edit] Changed return type to Derived* instead of Base*. 
    // Thanks to Matthieu for pointing this out. @see comments below. 
    virtual Derived* clone() const { return new Derived(*this); } 
    virtual void ID() const { printf("DERIVED"); } 
}; 

int main() 
{ 
    Derived d; 
    Base* bp = &d; 

    Base* bp2 = bp->clone(); 
    bp2->ID(); // outputs DERIVED as expected 
    delete bp2; 
} 
+1

Me apolgize a todos ... Creé un ejemplo simple y lo publiqué, tratando de evitar enterrar a todos en el código real ... pero cometí varios errores en la versión simple, y antes de que pudiera volver y corregirlos, ¡Tuvo varias respuestas! En este punto, no sé cuál de las respuestas está respondiendo mi buggy example, que sigue perteneciendo a mi pregunta real ... – wanlessv

+0

También es mejor usar un puntero inteligente (como boost :: shared_ptr) para borre automáticamente bp2. –

+0

@Daniel Sí, pero creo que si el OP tiene dificultades con la herencia y el polimorfismo, podría pasar un tiempo antes de que pueda comprender el RAII y los indicadores inteligentes. – stinky472

7

Una vez que todos los errores de compilación son fijos, terminé con esto:

#include <cstdio> 

class Base 
{ 
    public: 
    Base() {} 
    Base(const Base&) {} 
    virtual Base *clone() { return new Base(*this); } 
    virtual void ID() { printf("BASE"); } 
}; 

class Derived : public Base 
{ 
    public: 
    Derived() {} 
    Derived(const Derived&) {} 
    virtual Base *clone() { return new Derived(*this); } 
    virtual void ID() { printf("DERIVED"); } 
}; 


int main() 
{ 
    Derived d; 
    Base *bp = &d; 
    Base *bp2 = bp->clone(); 

    bp2->ID(); 
} 

que le da lo que busca - derivada.

+0

Gracias a todos por su tiempo. Estudiando este ejemplo, creo que entiendo el problema. – wanlessv

0

El código se ve bien, aparte de los tontos errores de sintaxis y los códigos faltantes.

Cuestiones relacionadas