为什么RTTI是必需的?

问题描述:

为什么RTTI(运行时类型信息)是必需的?为什么RTTI是必需的?

+5

+1,仅用于补偿downvote。不要对新手有意思。 – pyon 2010-04-16 03:32:16

+0

闻起来像功课。 – x0n 2010-04-16 03:37:48

+5

不要“赔偿”downvotes,要么。如果您认为这是一个好问题,请Upvote - 目前的投票不应该影响这一点。 – EMP 2010-04-16 04:20:34

RTTI,运行时类型信息,为C++引入了一种[温和]反射形式。

它允许知道例如超类的类型,因此允许处理从相同基类型派生的对象的异类集合。以特定于各个超级班的方式。 (假设您有一组“车辆”对象,需要对在阵列中找到的“卡车”对象进行不同的处理)。

RTTI是否需要是一个开放的问题。故事情况表明,Bjarne Stroustrup有意将该功能从原始的C++规范中排除,因为担心它会被滥用。
确实有机会过度使用/滥用反射功能,而当C++最初被引入时,这可能更是一个因素,因为在主流程序员社区中没有这样的OOP文化。这就是说,有了更多的面向对象的精明社区,有效地演示了反射可以做的所有好事(例如用诸如Java或C#等语言)以及现今使用的花哨设计模式,我坚信RTTI即使有时误用,反射特征也非常重要。

+1

Stroustrup的担忧是有道理的。它的大部分用途似乎在压制和普遍违反OO规则。现在,人们希望它更合理,更合理地使用。 – Duncan 2010-04-16 03:45:19

+0

@Duncan:我同意。在介绍一些明确的RTTI处理之前,在我的设计中,我问自己:“在这种情况下,这是一种代码味道吗?”,而且有时我最终会修改一些接口,以某种方式重构并避免使用反射。 – mjv 2010-04-16 03:54:22

+2

RTTI的一个奇妙的用途是'boost :: any'。 – GManNickG 2010-04-16 03:55:03

我可以想到一个恰当的使用RTTI的情况,它甚至不能工作。

C兼容API执行回调以提供用户定义的void *来将状态结构传递回调用方是相当普遍的。当从C++调用这样一个API时,通过void *参数传递这个指针是很常见的。从回调中,可能需要在传入的指针上调用虚函数。

在某些情况下,如果回调参数不安全(例如Windows消息的LPARAM),通过检查隐藏的vfptr,显然需要在将其用于虚拟调用之前验证指针。 dynamic_cast是这样做的自然方式,但是当对象无效时(IIRC,如果指针指向的是除虚拟表的对象之外的任何其他指针,则是未定义的行为)会导致未定义的行为。所以RTTI以这种方式完全没有用来防止破碎的攻击。

随意提供RTTI的任何其他有效用例,因为我完全不相信。

编辑:boost::any得到提及。至于boost::any而言,您可以禁用RTTI并使用以下typeid实现:

typedef const void* typeinfo_nonrtti; 
template <typename T> typeinfo_nonrtti typeid_nonrtti(); 
template <typename T> class typeinfo_nonrtti_helper 
{ 
    friend typeinfo_nonrtti typeid_nonrtti<T>(); 
    static char unique; 
}; 
template <typename T> char typeinfo_nonrtti_helper<T>::unique; 

template <typename T> 
typeinfo_nonrtti typeid_nonrtti() { return &typeinfo_nonrtti_helper<T>::unique; } 
+0

就像我上面所说的,'boost :: any'。 :) – GManNickG 2010-04-16 05:28:41

+1

对于我来说看起来不像RTTI,看起来它会使用在持有者'模板实例化时推断的编译时类型。如果它是RTTI,那么你遇到了严重的麻烦,因为any_cast'基于typeid而不是子类匹配进行匹配匹配,所以实际上不可能将值返回(你必须'any_cast'对象的确切运行时类型,而不是你放入的类型,如果类型是多态的话)。我从来没有使用'boost :: any',并且基于对源代码的粗略检查,永远不会。太脆弱了。 – 2010-04-16 05:49:19

+0

不好意思,'boost :: any'使用'typeid(ValueType)',而不是'typeid(value)'。因此,即使类型是多态的,它也是纯粹的编译时类型信息。完全没用,你可以在没有'typeid'或使用RTTI的情况下获得相同的效果。 – 2010-04-16 05:54:58