【问题标题】:Practical uses of exploiting RTTI in C++在 C++ 中利用 RTTI 的实际用途
【发布时间】:2013-07-06 00:09:21
【问题描述】:

已经完成了第一卷。在 Bruce Eckel 的 Thinking in C++ 中,我已经开始阅读第 2 卷。专门讨论RTTI(运行时类型识别)的章节最让我惊讶。我一直在阅读有关tyepiddynamic_cast 等的信息。

但是,我有一个问题浮现在我的脑海中。他们是否通过提到的运营商来利用RTTI 的任何实际用途,即来自现实项目的一些示例?另外,遇到了哪些限制使其需要使用?

【问题讨论】:

  • 实用,是的。常见的,没有。对于大多数应用程序来说,它的使用应该很少见。我猜 RTTI 的最大用途是实现boost::any,它检查你get() 的类型是否与你分配的相同。
  • 我从未见过也没有使用过typeid 任何严重的地方,但dynamic_cast 对于一些 运行时多态性很有用。关于dynamic_cast,如果你需要使用它,它通常(但不总是,当然)是糟糕设计的标志。
  • 这里是使用typeid's - stackoverflow.com/a/17549551/381333的示例

标签: c++ casting rtti typeid


【解决方案1】:

我在旅行中看到的生产代码中最常见的 RTTI 示例是 dynamic_cast,但它几乎总是被用作糟糕设计的创可贴。

dynamic_cast 主要用于多态类,然后用于从基类到派生类。但是想想看。如果您有一个指向正确设计的多态类的基指针,为什么还需要指向派生类型的指针?理论上,您应该只需要调用virtual 函数,并让实际的实例化处理实现细节。

话虽如此,在某些情况下,即使dynamic_cast 是一个创可贴,它仍然是两害相权取其轻。当“修复”损坏的设计意味着大型维护项目并且不会影响性能时,尤其如此。假设您有一个 1 MLOC 应用程序,并且修复学术上被破坏的东西将意味着必须接触 10 万行代码。如果没有性能方面的原因进行更改,那么您只是为了修复它而修复它,但是您冒着创建数十或数百个新错误的风险。这可能不值得。

【讨论】:

  • 理论上,主流语言中的表达问题没有解决方案,您可能需要的不仅仅是虚函数来获得足够好的设计。仍然可以说 dynamic_cast 是一个设计不佳的类型系统的创可贴。 :)
  • 我不太明白。
  • @John Dibling:坦率地说,我多次听到这种“糟糕的设计”的说法。但与此同时,对于典型的日常问题,我还没有看到任何好的解决方案,例如,当我将 Derived 对象放在多态容器中时(例如,它存储 Base * 指针)。现在我希望我的Derived 对象恢复为Derived。如果没有演员表,我怎么能做到这一点?这实际上是一个反问。没有强制转换的 C++ 中的 OOP 仅适用于简单的实验室级示例。任何严肃的实际编程都需要强制转换,而且没有办法。
  • @JohnDibling +1 为dynamic_cast,但typeid 上有任何特定的cmets?
  • 对于依赖于对象类型的操作,当这些操作不属于基类的虚拟成员时,动态转换是必要的。也就是说,当对象的行为取决于它是什么类时,您只需添加一个虚拟方法。当第 3 方对象的行为取决于某事物是什么类时,该第 3 方类应该使用动态转换。
【解决方案2】:

dynamic_cast 对于添加可选功能很有用

void foo(ICoolStuff *cs) { auto ecs = dynamic_cast<IEvenCoolerStuff*>(cs); if (ecs != 0) { ecs->DoEvenCoolerStuff(); } cs->DoCoolStuff(); }

当您从头开始设计时,可能会将 DoEvenCoolerStuff 放入 ICoolStuff 并在不支持它的类中有空实现,但当您需要更改现有代码时通常不可行。

另一个用途是消息系统实现,其中可能使用 dynamic_cast 来区分您感兴趣的消息。更一般地说,当您面对the expression problem 时可能需要它。

【讨论】:

  • if (auto ecs = dynamic_cast&lt;IEvenCoolerStuff*&gt;(cs)) { ecs-&gt;DoEvenCoolerStuff(); }
  • 是的,我知道,但在这里没关系。
猜你喜欢
  • 2010-09-15
  • 2014-06-19
  • 2011-06-16
  • 1970-01-01
  • 2020-10-06
  • 1970-01-01
相关资源
最近更新 更多