Cómo clonar varios objetos herencia?
-
08-10-2019 - |
Pregunta
he definido una interfaz Cloneable:
struct Cloneable
{
virtual Cloneable * clone(void) const = 0;
}
Tengo también algunas otras clases de interfaz (contenido no es relevante para emisión):
struct Interface
{
};
struct Useful_Goodies
{
};
He creado un objeto hoja que hereda de las clases anteriores:
struct Leaf : public Cloneable, public Interface, public Useful_Goodies
{
Leaf * clone(void) const // Line #1 for discussion.
{
return new Leaf(*this);
}
};
Estoy recibiendo el error:
overriding virtual function return type differs and is not covariant from 'Cloneable::clone'
Si cambio el tipo de Cloneable *
, me sale este mensaje de error:
'return' : ambiguous conversions from 'Leaf *' to 'Cloneable *'
Mis Preguntas (todos relacionados):
- ¿Cómo puede resolver la clase hoja de la
requisitos de la
Cloneable
interfaz? - ¿Hay una mejor solución para implementar una La clonación de contrato, donde todos los objetos están garantizados para poner en práctica la clonación?
Estoy usando este paradigma como parte de la programación genérica (registros, campos y base de datos).
Compilador: MS Visual Studio 2008; Plataformas: Windows XP y Vista ??em>
Solución
Tener su retorno de la función clone
un Cloneable *
es correcta.
Se obtendrá una conversión ambigua si uno de sus interfaces de deriva también de Cloneable
.
Editar Alf señala en los comentarios que no sólo es posible para Leaf::clone
para devolver una Leaf*
, en realidad es preferible que lo haga. Mi error.
Otros consejos
Es probable que no se menciona que Interface
o alguna otra clase de base también Cloneable
hereda. Los medios "conversión" ambigua Leaf
probablemente contiene múltiples sub-objetos de la clase base Cloneable
. (Un problema con el tipo de devolución covariante podría ser un resultado directo del mismo problema.)
Usted querrá resolver este problema utilizando virtuales herencia (recomendada y vinculado lectura: temas de C ++ FAQ Lite 25.8 través 25.13). Para empezar, el cambio todos casos de : public Cloneable
a : public virtual Cloneable
.
puedo arriesgar y decir que usted está probablemente no virtualmente heredando de Cloneable
de más de un camino. Es decir, algo de su otra base, además de los hereda Cloneable
directos (directa o indirectamente) de Cloneable
. Esto hace que la conversión de Leaf*
a Cloneable*
ambigua, ya que hay más de una base Cloneable
en su Leaf
.
La solución simple es utilizar la herencia virtual a partir de la interfaz:
struct Cloneable {
virtual Cloneable * clone() = 0;
};
struct Interface : virtual Cloneable {
};
struct Test : virtual Cloneable, Interface {
virtual Test* clone() {
return new Test(*this);
}
};
medios herencia virtual que incluso si ambos Interface
y Test
Heredar del Cloneable
, sólo hay un único objeto base Cloneable
.