代码之家  ›  专栏  ›  技术社区  ›  aitor

C++中的反射

  •  12
  • aitor  · 技术社区  · 16 年前

    我已经用Java工作了很多年。在那些年里,我广泛地(或者可能只是频繁地)使用了反射,发现它有用而且令人愉快。但8个月前,我换了工作,现在Java只是一个内存,我掌握了C++。所以现在我想知道C++中是否有反射机制。我读过RTTI,但我觉得它绝不是Java(或其他语言)反射的力量。我认为在C++中没有办法做到这一点。我错了吗?

    8 回复  |  直到 16 年前
        1
  •  5
  •   j_random_hacker    16 年前

    如果你正在寻找一个完全通用的方法来在运行时操纵对象,当你在C++中不知道编译时的类型时,你基本上需要:

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

    现在,假设 pFoo 保留类型的接口指针 IFoo* 对某些对象 x (你不需要知道 X 的混凝土类型)。您可以看到这个对象是否支持接口 IBar 说:

    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();
    }
    

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

    另一个需要考虑的方面是 对象创建 .要在不知道具体类型的情况下完成这一点,您需要一个工厂函数,加上类的唯一标识符来指定您想要的具体类。可以安排类在启动时向全局工厂注册, as described here by C++ expert Herb Sutter --这样就避免了 switch 声明,大大简化了维护。可以使用单个工厂,尽管这意味着系统中的每个对象都必须实现一个接口(工厂将返回指向此接口类型的指针或引用)。

    一天结束时,你最终得到的基本上是(同构于) COM —— dynamic_cast<IFoo*> 做同样的工作 QueryInterface(IID_IFoo) ,所有对象实现的基本接口等效于 IUnknown .

        2
  •  15
  •   hhafez    16 年前

    由于C++标准不包括“元数据”这样的概念,所以除了您已经提到的RTTI之外,没有可移植的(跨不同的编译器和平台),这是运行时反射的方法。

    在C++中,也有编译时间反射的可能性(思考)。 boost::type_traits boost::type_of 但与尼默尔或Lisp相比,它是有限的。

    大多数主要框架(MFC、Qt等)允许您在运行时提取元信息,但它们需要各种特殊的注释才能使其工作(请参见 RUNTIME_CLASS 以此类推)。

        3
  •  4
  •   Community CDub    8 年前

    看一看 my answer to a similar question . 这两种解决方案(xrti和openc++)都是基于在构建过程中为您生成反射元数据的外部工具提出的。

        4
  •  3
  •   Daniel Earwicker    16 年前

    你需要使用访客模式。任何可以反映的类都需要继承一个基类,该基类为 Reflect 成员函数,它将接受访问者类。然后 反映 函数将其他成员的信息或功能传递给访问者。

    许多流行的库在特定的情况下使用这种模式,例如 Serialize MFC中的函数执行此操作,但专门用于序列化。

    您可以设计一个系统,使访问者能够动态调用成员函数、获取或设置数据成员的值等,但是每个类都有责任维护 反映 手工编写的函数,这将是类结构的重复。

        5
  •  1
  •   Benoît photo_tom    16 年前

    RTTI是一种解决方案(Java中的哪一部分您认为不是RTTI?)否则,你可以实现你自己的对象框架——让每个你自己的C++对象继承一些反射接口,然后它应该工作。

        6
  •  1
  •   MickaelFM    16 年前

    反射是计算机程序观察和修改自身结构和行为的过程。我不知道如何在C++中进行反射。RTTI只对运行时内存中对象的数据类型有用。

        7
  •  0
  •   Roboprog    16 年前

    如果您将它用于依赖项注入(某个接口^h^h^h^h^h^纯抽象类的实现),则可以尝试动态加载.dll或.so文件,这些文件包含插件的任何内容的当天实现。

    可能只是抓住了稻草,因为这对同时实现多个事物来说不太好。

        8
  •  0
  •   Roderick    15 年前

    在C++中你需要做什么,你在用什么平台?我知道一种使用这些数据获取完整类定义和调用函数的方法,它在Windows中工作,但我不知道其他平台。其思想是从dll或exe导出表中获取数据。这并不容易——我们花了几个月的时间才得到一个像样的实现——但是它将做反射支持语言所做的一切。