用C++反思

ait*_*tor 12 c++ java reflection

我一直在使用Java工作多年.在那些年里,我已经广泛(或者可能只是经常)使用反射,并发现它有用且令人愉快.但是8个月前我改变了我的工作,现在Java只是一个记忆,我正在接受C++.所以现在我想知道C++中是否有任何反射机制.我读过有关RTTI的内容,但我觉得这绝不是Java(或其他语言)反射的强大功能.我开始认为在C++中没有办法做到这一点.我错了吗?

Ant*_*lev 15

由于C++标准没有涵盖"元数据"这样的概念,因此除了您已经提到的RTTI之外,没有可移植的(跨不同的编译器和平台)运行时反射方法.

在C++中,还存在编译时反射(思考boost::type_traitsboost::type_of)的可能性,但与Nemerle或LISP相比,它也是有限的.

大多数主要框架(MFC,Qt等)允许您在运行时提取元信息,但它们需要各种特殊注释才能工作(请参阅RUNTIME_CLASS等作为示例).


j_r*_*ker 5

如果您正在寻找一种在运行时操作对象的完全通用的方法,当您在C++编译时不知道它们的类型时,您基本上需要:

  1. 为类可能支持的每个功能定义一个接口(具有所有纯虚方法的抽象基类,没有成员).
  2. 每个类必须从它想要实现的所有接口(可能在其他类中)中虚拟继承.

现在,假设为某个对象pFoo保存了一个类型的接口指针(您不需要知道具体类型).您可以通过以下方式查看此对象是否支持接口:IFoo*xxIBar

if (IBar* pBar = dynamic_cast<IBar*>(pFoo)) {
    // Do stuff using pBar here
    pBar->endWorldHunger();
} else {
    // Object doesn't support the interface: degrade gracefully
    pFoo->grinStupidly();
}
Run Code Online (Sandbox Code Playgroud)

这种方法假设您在编译时了解所有相关接口 - 如果不这样做,您将无法使用普通的C++语法来调用方法.但是很难想象调用程序不知道它需要什么接口的情况 - 关于我能想到的唯一情况是,如果你想通过交互式解释器公开C++对象.即使这样,你也可以设计一种(丑陋的,维护密集的)将这种方式用于上述范例的方法,以便通过将它们的名称和参数指定为字符串来调用方法.

要考虑的另一个方面是对象创建.要在不知道具体类型的情况下完成此操作,您需要一个工厂函数,以及类的唯一标识符,以指定您想要的具体类.如C++专家Herb Sutter所描述的那样,可以安排课程在启动时向全球工厂注册自己- 这避免了保持巨大的switch声明,大大简化了维护.可以使用单个工厂,但这意味着系统中的每个对象都必须实现一个接口(工厂将返回指针或对此接口类型的引用).

在一天结束时,你最终得到的东西基本上是(同构的)COM - dynamic_cast<IFoo*>做同样的工作QueryInterface(IID_IFoo),并且所有对象实现的基本接口相当于IUnknown.