No exemplo, por cada vez que um método é invocado, é impressa uma mensagem no écran. A classe do objecto chama-se Person. O objecto é controlado por um metaobjecto, que altera o código da chamada ao objecto.
//---- person.c ---- #include <stdio.h> #include "prnmetaobj.h" // Contém a declaração do metaobjecto. class Person { Person(char *name, int age); int Age(); //MOP reflect : int IncAge(); // Incrementa a idade e retorna-a. private: char *name; int age; };
A linha que começa com //MOP indica que a execução dos métodos que se seguem é controlada por um metaobjecto. Estes métodos são chamados reflect. Neste caso, apenas o método IncAge é afectado.
//---- person.c (cont.) ---- //MOP reflect class Person : PrintMetaObj; Person::Person(char *n, int a) { name = n; age = a; } int Person::Age() { return age; } int Person::IncAge() { return ++age; }
A segunda linha começada por //MOP, determina que um objecto da classe Person pode ser reflexivo e que o seu metaobjecto é da classe PrintMetaObj. Isto não é rigorosamente verdade, mas é bastante aproximado. Na realidade, o compilador, ao encontrar a linha, vai produzir uma subclasse de Person, refl_Person. Objectos criados a partir de refl_Person são reflexivos, enquanto que os que são criados a partir de Person não são.
O código da classe do metaobjecto é apresentado de seguida.
//---- prnmetaobj.h ---- #include "metaobj.h" // Classe mãe... class PrintMetaObj : public MetaObj { public: void Meta_MethodCall(Id method_id, Id category, ArgPac &args, ArgPac &reply); }; //---- prnmetaobj.c ---- #include <stdio.h> #include "prnmetaobj.h" void PrintMetaObj::Meta_MethodCall(Id method_id, Id category, ArgPac &args, ArgPac &reply) { printf("*** %s was called.\n", Meta_GetMethodName(m_id)); Meta_HandleMethodCall(m_id, args, reply); }
A classe PrintMetaObj redefine o método Meta_MethodCall para escrever uma mensagem por cada chamada a um dos métodos reflect. Os quatros argumentos do método representam o identificador, method_id, a categoria, category, uma referência para os dados de entrada do método, args, e uma referência para os dados de retorno, reply. O método original, neste caso IncAge, é executado por Meta_HandleMethodCall, que recebe o seu identificador. No fim da execução do método Meta_MethodCall, o valor referenciado por reply é passado ao chamador como valor de retorno do método chamado, IncAge (ver figura 2.4).