Pregunta

Sabemos que podemos resolver el problema de diamantes usando la herencia virtual.

Por ejemplo:

   class Animal // base class
   {
     int weight;
     public:
     int getWeight() { return weight;};
   };
   class Tiger : public Animal { /* ... */ }; 
   class Lion : public Animal { /* ... */ };
   class Liger : public Tiger, public Lion { /* ... */ }; 
   int main()
   {
     Liger lg ;
     /*COMPILE ERROR, the code below will not get past
     any C++ compiler */
     int weight = lg.getWeight();
   }

Cuando compilemos este código, recibiremos un error de ambigüedad. Ahora mi pregunta es cómo el compilador detecta internamente este problema de ambigüedad (problema de diamantes).

¿Fue útil?

Solución

El compilador construye tablas que enumeran a todos los miembros de cada clase, y también tiene enlaces que le permiten subir y bajar la cadena de herencia para cualquier clase.

Cuando necesita ubicar una variable miembro (peso en su ejemplo), el compilador comienza desde la clase real, en su caso Liger. No encontrará un miembro de peso allí, por lo que luego mueve un nivel a las clases principales. En este caso hay dos, por lo que escanea tanto a Tiger como a Lion para un miembro de Name Weight. Todavía no hay éxitos, por lo que ahora debe subir un nivel más, pero debe hacerlo dos veces, una vez para cada clase en este nivel. Esto continúa hasta que el miembro requerido se encuentra en algún nivel del árbol de herencia. Si en algún nivel dado encuentra solo un miembro considerando todas las ramas de herencia múltiples, todo es bueno, si encuentra dos o más miembros con el nombre requerido, entonces no puede decidir cuál elegir para que sea errores.

Otros consejos

Cuando el compilador crea una mesa de punteros de función para una clase, cada símbolo debe aparecer en ella exactamente una vez. En este ejemplo, getWeight aparece dos veces: en Tiger y en Lion (porque Liger No lo implementa, por lo que sube el árbol para buscarlo), por lo que el compilador se atasca.

Es bastante simple, en realidad.

El compilador busca GetWeight en Liger, no encuentra ninguno, luego verifica a sus padres y a los padres de sus padres, etc., y así sucesivamente, si encuentra más de uno, le devuelve un error y muere, porque no puede decir cuál es. debería usar.

Con su código, la estructura para Liger es

Liger[Tiger[Animal]Lion[Animal]]

Si llamas a un Animal función de un Liger puntero, en realidad hay dos animales a los que puede convertir (de ahí la ambigüedad)

La herencia virtual generará una estructura como

Liger[Tiger[*]Lion[Animal]]
            \-----/

Ahora solo hay un animal, indirectamente accesible desde ambas bases, por lo que una conversión de Liger a animal es más ambigua.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top