我希望能够自省一个c++类的名称,内容(即成员及其类型)等。这里我说的是原生c++,而不是托管c++,托管c++有反射。我意识到c++使用RTTI提供了一些有限的信息。哪些附加库(或其他技术)可以提供这些信息?


当前回答

如果你像这样声明一个指向函数的指针:

int (*func)(int a, int b);

您可以像这样在内存中为该函数分配一个位置(需要libdl和dlopen)

#include <dlfcn.h>

int main(void)
{
    void *handle;
    char *func_name = "bla_bla_bla";
    handle = dlopen("foo.so", RTLD_LAZY);
    *(void **)(&func) = dlsym(handle, func_name);
    return func(1,2);
}

要使用间接方式加载局部符号,可以对调用二进制文件(argv[0])使用dlopen。

这样做的唯一要求(除了dlopen()、libdl和dlfcn.h)是知道函数的参数和类型。

其他回答

我也想要一匹小马,但小马不是免费的。: - p

http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI是你将得到的。像您所考虑的反射——运行时可用的完整描述性元数据——在默认情况下c++中不存在。

周围有两种反射。

Inspection by iterating over members of a type, enumerating its methods and so on. This is not possible with C++. Inspection by checking whether a class-type (class, struct, union) has a method or nested type, is derived from another particular type. This kind of thing is possible with C++ using template-tricks. Use boost::type_traits for many things (like checking whether a type is integral). For checking for the existence of a member function, use Templated check for the existence of a class member function? . For checking whether a certain nested type exists, use plain SFINAE .

如果你想要实现1),比如查看一个类有多少个方法,或者获取一个类id的字符串表示形式,那么恐怕标准c++没有办法做到这一点。你必须使用其中任何一个

一个元编译器,如Qt元对象编译器,它翻译你的代码,添加额外的元信息。 由宏组成的框架,允许您添加所需的元信息。你需要告诉框架所有的方法、类名、基类和它需要的一切。

c++的设计考虑到了速度。如果您想要高级别的检查,就像c#或Java所做的那样,不做一些额外的工作就无法做到这一点。

这些信息确实存在——但不是你需要的格式,而且只有当你导出你的类时。这适用于Windows,我不知道其他平台。使用存储类说明符,例如:

class __declspec(export) MyClass
{
public:
    void Foo(float x);
}

这使得编译器将类定义数据构建到DLL/Exe中。但它不是一种可以用于反射的格式。

在我的公司,我们建立了一个解释元数据的库,允许你在不插入额外的宏等到类本身的情况下反映一个类。它允许如下方式调用函数:

MyClass *instance_ptr=new MyClass;
GetClass("MyClass")->GetFunction("Foo")->Invoke(instance_ptr,1.331);

这有效地做到:

instance_ptr->Foo(1.331);

Invoke(this_pointer,…)函数有可变参数。显然,通过这样调用函数,你可以绕过诸如const-safety之类的东西,所以这些方面是作为运行时检查实现的。

我相信语法可以改进,到目前为止它只适用于Win32和Win64。我们发现它非常有用,可以为类提供自动GUI接口,在c++中创建属性,流到XML和从XML输出等等,而且不需要从特定的基类派生。如果有足够的需求,也许我们可以把它做成样子发布。

编辑:不再维护CAMP;有两个fork可供选择:

其中一个也被称为CAMP,并且基于相同的API。 思考是部分重写,应该优先考虑,因为它不需要Boost;它使用c++ 11。


CAMP是MIT授权的库(以前是LGPL),它向c++语言添加了反射。它在编译中不需要特定的预处理步骤,但是必须手动进行绑定。

目前的Tegesoft库使用Boost,但也有一个使用c++ 11的分支不再需要Boost。

当我想要在c++中进行反射时,我读了这篇文章并改进了我在那里看到的东西。对不起,没有罐头。结果不是我的…但你当然可以得到我所拥有的,然后从那里开始。

我目前正在研究,当我喜欢的时候,使用inherit_linear的方法使可反射类型的定义更容易。实际上我已经学了很多,但还有一段路要走。c++ 0x中的变化很可能在这方面有很大的帮助。