... Nota, Herb Sutter escribió 3 artículos excelentes sobre la herencia múltiple (1) here, (2) here y (3) here. Escribió un montón de artículos útiles en el gurú de la semana here. Muy recomendable ...
En primer lugar, no estoy seguro de obtener su jerarquía correcta. Lo tomo es así:
struct A {
virtual void F() = 0;
};
struct B : A { void F() { } };
struct C : A { };
struct D : B, C { };
Bueno, D es abstracto, porque hay dos A
subobjetos en un objeto de tipo D: uno que está hecho de hormigón mediante B
través de la red de B, y uno que sigue siendo abstracto en el enrejado pasando por C
. Supongo que tiene un puntero al D
y trata de llamar al F
. Sí, se presenta una ambigüedad, porque el compilador encuentra dos funciones F
en dos redes separadas:
D -> B::F
D -> C -> A::F
aspecto:
F() F()
A A
| |
F() B C
\ /
D
Puede corregir esa situación formalmente mediante la derivación de la A virtualmente:
struct B : virtual A { void F() { } };
struct C : virtual A { };
struct D : B, C { };
A continuación, tiene esta situación, se llama la herencia de diamantes:
F()
A
/ \
F() B C
\ /
D
Y al hacer la búsqueda, se encuentra que hay B::F
anulando A::F
. Aunque todavía puede comunicarse con A::F
a través de D::C::A
, ya no es una ambigüedad, ya que A
se hereda virtual.
Si esta es la solución correcta para su problema en particular, eso por supuesto no es seguro. En general, hay mejores formas de derivar virtual de una clase. A su pregunta sobre la fusión de tablas de funciones virtuales, eso depende completamente de la implementación. GCC
, por lo que sé, mantendrá un puntero a la única instancia A en la tabla virtual de D
, si derivamos virtual.
Gracias. Esto es sobre lo que he preguntado. Si la funcionalidad depende del desarrollo del compilador, no es posible. –
el comportamiento es el mismo para cada compilador: la compilación de los compiladores es diferente. Puede confiar en que los compiladores se comportan como los demás, siempre y cuando no dependa de un diseño particular del objeto (como el tamaño del valor) que dependería de una implementación. –
Ok, déjame preguntar con más precisión: si hay herencia virtual de diamante y hay una función definida en A y B, pero no en C, ¿puedo acceder a la función a través de D? ¿Y cuál sería ese, el definido en A o el de B? ¿El comportamiento es consistente para todos los compiladores? –