Gostaria de fazer algo semelhante a um Objet Inspector, porém gostaria
de saber como posso pegar as __property de uma classe em run-time (nome,
tipo, etc), de maneira que consiga pegar e modificar as propriedades de
qualquer classe minha.
Obrigado,
___________________________________________
Maycon Maia Vitali ( 0ut0fBound )
__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/
Existe a biblioteca typeinfo. Segue um exemplo de codigo.#include<iostream>#include<typeinfo>class A{};int main(){A a;std::cout<<typeid(a).name();}Mais detalhes podem ser visto no cplusplus:
http://www.cplusplus.com/reference/std/typeinfo/
Abraços.
#include <vcl.h>
#include <iostream>
#pragma hdrstop
#pragma package(smart_init)
int main( void )
{
TMetaClass *meta;
TStringList* strlst = new TStringList;
//int intv = 0;
/* meta = __classid(strlst);
* Error E2303 classid.cpp 13: Type name expected in function
main() */
meta = __classid(TStringList);
std::cout << "Class name: " <<
((AnsiString)meta->ClassName()).c_str() << std::endl;
meta = strlst->ClassType();
std::cout << "Class name: " <<
((AnsiString)meta->ClassName()).c_str() << std::endl;
/* meta = __classid(intv);
* Error E2303 classid.cpp 21: Type name expected in function
main() */
/* meta = __classid(int);
* Error E2242 classid.cpp 23: __classid requires VCL style class
type in function main() */
//std::cout << "Class name: " <<
((AnsiString)meta->ClassName()).c_str() << std::endl;
delete strlst;
}
Maycon, você pode começar analizando o arquivo "systobj.h" que está
na pasta "Include/Vcl". O método de seu interesse é o método
ClassInfo() que, infelizmente, retorna um "void*":
>>>>
Returns a pointer to the run-time type information (RTTI) table for
the object type.
typedef TMetaClass* TClass;
static void * __fastcall ClassInfo(TClass cls);
void * __fastcall ClassInfo(){return ClassInfo(ClassType()); }
Description
Use ClassInfo to access the RTTI table that contains information
about the object type, its ancestor type, and all of its published
properties (...)
<<<<
Com uma boa pesquisada no Google, você deve encontrar alguma
informação, mas provavelmente você terá problemas com as diferenças
entre as diversas versões do compilador.
> Na verdade, os componentes visuais do Delphi, que você exemplificou,
> precisam seguir uma convenção para que o IDE os reconheça como
> componentes. Isso não é intrínseco da linguagem. O mesmo se diga à
> respeito do C++ builder.
Olha, na verdade bem verdadeira, é uma mistura de linguagem e compilador (apesar das duas coisas serem as vezes a mesma coisa). No Delphi (e imagino que seja semelhante no C-Builder), é preciso que uma classe herde de uma classe especifica (TComponent) e que todos as propriedades que devem aparecer no editor de propriedades do IDE sejam declaradas dentro de 'published' (que é um escopo semelhante ao 'public' com a única diferença que ele aparece no IDE). O pascal por si só pode ou não ter isso; depende para quem você pergunta. Ou seja, não é só uma convenção; tem gambiarra no compilador já que o compilador gera um código especial para os métodos que estão em 'published'. Isso é algo normal para pascal já que por exemplo o tipo string é implementado pelo compilador, e não é uma classe como no C++. O complilador gera um ponteiro, onde coloca um contador de referência (para fazer COW), depois um int com o tamanho do string e finalmente os chars com um NULL no final para manter compatibilidade com C. Isso faz uma zona quando se usa DLLs em delphi, pois o gerenciador de memória se perde fácil (ou pelo menos quando eu usava Delphi, ouvi falar que isso foi resolvido).
Falando específicamente de C++, além do C-Builder, o Qt tem algo semelhante, com exemplos aqui:
http://doc.qt.nokia.com/4.6/properties.html
Declarando propriedades de uma classe:
Q_PROPERTY(bool focus READ hasFocus)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(QCursor cursor READ cursor WRITE setCursor RESET unsetCursor)
Alterando valores de propriedades:
QPushButton *button = new QPushButton;
QObject *object = button;
button->setDown(true);
object->setProperty("down", true);
E listando propriedades:
QObject *object = ...
const QMetaObject *metaobject = object->metaObject();
int count = metaobject->propertyCount();
for (int i=0; i<count; ++i) {
QMetaProperty metaproperty = metaobject->property(i);
const char *name = metaproperty.name();
QVariant value = object->property(name);
...
}
O Qt faz isso pois introduz um meta-object compiler, que é uma ferramenta que lê os .h e gera um .cpp que implementa tudo isso. Nada mais é que uma ferramenta de linha de comando 'moc' que se coloca no Makefile.