Nesta secção mostra-se um pequeno programa que ilustra a capacidade do modelo para lidar com casos de herança múltipla. O código apresentado foi gerado manualmente e não deve ser tomado como sendo o formato final dos envelopes. O que aqui se pretende demonstrar é a consistência dos resultados do programa quando se substituem transparentemente os objectos do programa por envelopes, em presença de herança múltipla e na presença de conversões de tipos e polimorfismo de inclusão.
A macro DYNCAST representa uma operação do gestor de tipos, que se supõe existir no sistema final, que determina qual o tipo exacto de um objecto dentro de um envelope, sob a forma de zona de memória não tipificada.
A operação consiste em converter correctamente o ponteiro não tipificado para o tipo com o qual o objecto foi criado originalmente e depois convertê-lo para o tipo necessário à execução correcta da operação pretendida.
Note-se que, por uma questão de clareza, os nomes das classes das cartas e dos envelopes não seguem as normas definidas em capítulos anteriores. Os nomes das classes dos envelopes diferem dos das cartas pelo acrescento aos nomes daquelas da letra `` e''. Assim, A, B e C representam classes de cartas e Ae, Be e Ce de envelopes.
// Isto não é assim que funciona na realidade... // No sistema real, existe um gestor de tipos que sabe fazer esta // operação a um nível mais alto. #define DYNCAST(l) ((C*)(l)) //---- CLASSES ---- class A { public: int a() { printf("aaaa\n"); } virtual int b() { printf("aaaa\n"); } }; class B : virtual public A { public: int a() { printf("bbbb\n"); } virtual int b() { printf("bbbb\n"); } }; class D : virtual public A { public: int a() { printf("dddd\n"); } virtual int b() { printf("dddd\n"); } }; class C : public B, public D { public: int a() { printf("cccc\n"); } virtual int b() { printf("cccc\n"); } }; //---- MAIN ENVELOPE CLASS ---- class Envelope { protected: void *l; }; //---- OTHER ENVELOPE CLASSES ---- class Ae : public Envelope { public: inline Ae() { if (!l) l = (void*)new A; } inline int a() { ((A *)DYNCAST(l))->A::a(); } inline virtual int b() { ((A *)DYNCAST(l))->A::b(); } }; class De : virtual public Ae { public: inline De() { if (!l) l = (void *)new D; } inline int a() { ((D *)DYNCAST(l))->D::a(); } inline virtual int b() { ((D *)DYNCAST(l))->D::b(); } }; class Be : virtual public Ae { public: inline Be() { if (!l) l = (void*)new B; } inline int a() { ((B *)DYNCAST(l))->B::a(); } inline virtual int b() { ((B *)DYNCAST(l))->B::b(); } }; class Ce : public Be, public De { public: inline Ce() { if (!l) l = (void*)new C; } inline int a() { ((C *)DYNCAST(l))->C::a(); } inline virtual int b() { ((C *)DYNCAST(l))->C::b(); } }; //---- MULTIPLE-INHERITANCE (LETTERS) ---- testML() { D *c = new C; printf("//----\n"); ((A *)c)->a(); //((B *)c)->a(); c->a(); printf("//----\n"); c->A::a(); //c->B::a(); c->a(); printf("//----\n"); ((A *)c)->b(); //((B *)c)->b(); c->b(); printf("//----\n"); c->A::b(); //c->B::b(); c->b(); } //---- MULTIPLE-INHERITANCE (ENVELOPES) ---- testME() { De *c = new Ce; printf("//----\n"); ((Ae *)c)->a(); //((Be *)c)->a(); c->a(); printf("//----\n"); c->Ae::a(); //c->Be::a(); c->a(); printf("//----\n"); ((Ae *)c)->b(); //((Be *)c)->b(); c->b(); printf("//----\n"); c->Ae::b(); //c->Be::b(); c->b(); } //---- ENVELOPES ---- testE() { Ce *c = new Ce; printf("//----\n"); ((Ae *)c)->a(); ((Be *)c)->a(); c->a(); printf("//----\n"); c->Ae::a(); c->Be::a(); c->a(); printf("//----\n"); ((Ae *)c)->b(); ((Be *)c)->b(); c->b(); printf("//----\n"); c->Ae::b(); c->Be::b(); c->b(); } //---- LETTERS ---- testL() { C *c = new C; printf("//----\n"); ((A *)c)->a(); ((B *)c)->a(); c->a(); printf("//----\n"); c->A::a(); c->B::a(); c->a(); printf("//----\n"); ((A *)c)->b(); ((B *)c)->b(); c->b(); printf("//----\n"); c->A::b(); c->B::b(); c->b(); } main() { testL(); printf("_____________________\n\n"); testE(); printf("_____________________\n\n"); testML(); printf("_____________________\n\n"); testME(); }