Pregunta

Considere:

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = new A( *b1 ); // ERROR...but what if it could work?
    return 0;
}

¿Se rompería C ++ si " nuevo A ( b1) " pudo resolver crear una nueva copia B y devolver una A ?

¿Sería esto útil?

¿Fue útil?

Solución

¿Necesita esta funcionalidad o es solo un experimento mental?

Si necesita hacer esto, el idioma común es tener un método Clone :

class A
{
public:
    A( int val ) : m_ValA( val ) {}
    A( const A& rhs ) {}
    virtual A *Clone () = 0;
    int m_ValA;
};

class B : public A
{
public:
    B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
    B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
    A *Clone() { return new B(*this); }
    int m_ValB;
};

int main()
{
    A* b1 = new B( 1, 2 );
    A* b2 = b1->Clone();
    return 0;
}

Otros consejos

Lo que realmente está buscando se llama constructor de copias virtuales , y lo que eduffy publicó es la forma estándar de hacerlo.

También hay formas inteligentes de hacerlo con plantillas . (descargo de responsabilidad: autopromoción)

Solo una pequeña adición a la respuesta de eduffy: En lugar de

class B : public A {
  ...
  A *Clone() { return new B(*this); } 
  ...

};

puedes declararlo así:

class B : public A {
  ...
  B *Clone() { return new B(*this); } // note: returning B *
  ...

};

Todavía se considera una anulación válida del A :: Clone (); virtual y es mejor si se llama directamente a través de B *

La expresión

new A(*b1)

ya tiene un significado, suponiendo que tuviera la sobrecarga adecuada.

Si se le diera un significado diferente, tendría que proporcionar otra forma de obtener el otro significado. Esto no tiene sentido dado que ya hay una manera de obtener el significado que desea:

new B(*b1)

Y adivina cuál es más claro de leer.

Sí No.

Hay varias formas de implementar la clonación (por ejemplo, el método clone () más o menos estándar, variaciones parametrizadas de fábricas de objetos, con o sin inyección de dependencia configurable) sin cambiar el significado de los programas existentes o hacer que sea imposible crear instancias de clases base cuando se conoce una clase derivada dentro de una unidad de compilación.

Los constructores y destructores son lo suficientemente complejos como para ser entendidos por los principiantes. Inyectar aún más complejidad en ellos sería imprudente.

Como se señaló anteriormente, hay varias formas de implementar esto.

Para responder a su pregunta si new A (* b1) devolvió una nueva instancia de B, entonces esto no funcionaría.

int main()
{
    A* b1 = new B( 1, 2 );
    A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
    return 0;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top