Jugué un programa en conjunto que podría ayudarte a estudiar las complejidades de las bases virtuales. Imprime la jerarquía de clases bajo I
como un dígrafo adecuado para graphiviz (http://www.graphviz.org/). Hay un contador para cada instancia que también te ayuda a comprender la orden de construcción. Aquí está la Programm:
#include <stdio.h>
int counter=0;
#define CONN2(N,X,Y)\
int id; N() { id=counter++; }\
void conn() \
{\
printf("%s_%d->%s_%d\n",#N,this->id,#X,((X*)this)->id); \
printf("%s_%d->%s_%d\n",#N,this->id,#Y,((Y*)this)->id); \
X::conn(); \
Y::conn();\
}
#define CONN1(N,X)\
int id; N() { id=counter++; }\
void conn() \
{\
printf("%s_%d->%s_%d\n",#N,this->id,#X,((X*)this)->id); \
X::conn(); \
}
struct A { int id; A() { id=counter++; } void conn() {} };
struct B : A { CONN1(B,A) };
struct C : A { CONN1(C,A) };
struct D : B { CONN1(D,B) };
struct E : B,C { CONN2(E,B,C) };
struct F : C { CONN1(F,C) };
struct G : D,E { CONN2(G,D,E) };
struct H : E,F { CONN2(H,E,F) };
struct I : G,H { CONN2(I,G,H) };
int main()
{
printf("digraph inh {\n");
I i;
i.conn();
printf("}\n");
}
Si funciono esto (g++ base.cc ; ./a.out >h.dot ; dot -Tpng -o o.png h.dot ; display o.png
), me sale el típico árbol de base no virtual: alt text http://i34.tinypic.com/2ns6pt4.png
añadiendo suficiente virtualidad ...
struct B : virtual A { CONN1(B,A) };
struct C : virtual A { CONN1(C,A) };
struct D : virtual B { CONN1(D,B) };
struct E : virtual B, virtual C { CONN2(E,B,C) };
struct F : virtual C { CONN1(F,C) };
struct G : D, virtual E { CONN2(G,D,E) };
struct H : virtual E,F { CONN2(H,E,F) };
struct I : G,H { CONN2(I,G,H) };
.. resultados en la forma del diamante (mira los números para aprender la orden de construcción !!)
alt text http://i33.tinypic.com/xpa2l5.png
Pero si haces todas las bases virtuales:
struct A { int id; A() { id=counter++; } void conn() {} };
struct B : virtual A { CONN1(B,A) };
struct C : virtual A { CONN1(C,A) };
struct D : virtual B { CONN1(D,B) };
struct E : virtual B, virtual C { CONN2(E,B,C) };
struct F : virtual C { CONN1(F,C) };
struct G : virtual D, virtual E { CONN2(G,D,E) };
struct H : virtual E, virtual F { CONN2(H,E,F) };
struct I : virtual G,virtual H { CONN2(I,G,H) };
obtienes un diamante con una orden de inicialización diferente:
alt text http://i33.tinypic.com/110dlj8.png
Diviértete!
¿Es esta una pregunta teórica o acabaste en una situación en la que esto tiene un valor real para ti? :) – falstro
En realidad, tenemos jerarquías de clases que se ven así (de hecho, son aún peores). Se planifica una refacturación ... – jchl
¡¡Es un escenario de herencia :)! – DumbCoder