next up previous contents index
Next: Index Up: Exemplos de Código Previous: Exemplo Utilizando Open

Invocação com Herança Múltipla

 

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();
}



David M. M. de Matos
Thu Jun 29 14:58:09 MET DST 1995