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


当前回答

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

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

其他回答

在我的c++生涯中,我知道的两个类似反射的解决方案是:

1)使用RTTI,如果你能够从一个“对象”基类派生所有的类,它将为你提供一个引导来构建类似反射的行为。该类可以提供一些方法,如GetMethod, GetBaseClass等。至于这些方法是如何工作的,你需要手动添加一些宏来装饰你的类型,这些宏在幕后创建类型的元数据,为GetMethods等提供答案。

2)如果你可以访问编译器对象,另一个选择是使用DIA SDK。如果我没记错的话,这允许您打开pdbs,其中应该包含c++类型的元数据。也许足够做你想做的事了。例如,本页展示了如何获取类的所有基类型。

这两种解决方案都有点难看!没有什么比c++更能让你欣赏c#的奢华了。

祝你好运。

这些信息确实存在——但不是你需要的格式,而且只有当你导出你的类时。这适用于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输出等等,而且不需要从特定的基类派生。如果有足够的需求,也许我们可以把它做成样子发布。

这个问题现在有点老了(不知道为什么我今天一直在问老问题),但我在想BOOST_FUSION_ADAPT_STRUCT,它引入了编译时反射。

当然,这取决于你将其映射到运行时反射,这不会太容易,但在这个方向上是可能的,而不是在相反的方向上:)

我真的认为一个宏来封装BOOST_FUSION_ADAPT_STRUCT可以生成必要的方法来获得运行时行为。

查看Classdesc http://classdesc.sf.net。它以类“描述符”的形式提供了反射,可以与任何标准c++编译器一起工作(是的,它可以与Visual Studio和GCC一起工作),并且不需要源代码注释(尽管存在一些处理棘手情况的pragmas)。它已经开发了十多年,并在一些工业规模的项目中使用。

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

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)是知道函数的参数和类型。