【发布时间】:2010-04-16 03:24:25
【问题描述】:
为什么需要 RTTI(运行时类型信息)?
【问题讨论】:
-
+1,只是为了补偿反对票。不要对新手刻薄。
-
也不要“补偿”反对票。如果您认为这是一个好问题,请投票支持 - 当前的投票根本不应该影响这一点。
标签: c++
为什么需要 RTTI(运行时类型信息)?
【问题讨论】:
标签: c++
RTTI,运行时类型信息,为 C++ 引入了一种 [温和的] 反射形式。
它允许知道例如超类的类型,因此允许处理所有从相同基类型派生的对象的异构集合。以特定于各个超类的方式。 (假设您有一个“Vehicle”对象数组,需要以不同方式处理在数组中找到的“Truck”对象)。
RTTI 是否是必要的问题是一个开放的问题。据说 Bjarne Stroustrup 故意从原始 C++ 规范中排除了这个特性,因为担心它会被滥用。
确实存在过度使用/误用反射特性的机会,这可能是最初引入 C++ 时的一个更大因素,因为在主流程序员社区中没有这样的 OOP 文化。
这就是说,有了一个更精通 OOP 的社区,有效地展示了反射可以做的所有好事(例如,使用 Java 或 C# 等语言)以及当今使用的花哨的设计模式,我坚信 RTTI 和反射即使有时被滥用,总体上的功能也非常重要。
【讨论】:
boost::any 是 RTTI 的绝妙用法。
我只能想到一种适合使用 RTTI 的情况,但它甚至不起作用。
执行回调以提供用户定义的 void* 以将状态结构传回给调用者的 C 兼容 API 相当常见。当从 C++ 调用这样的 API 时,通过 void* 参数传递 this 指针是很常见的。从回调中,人们可能想要在传递的指针上调用虚函数。
在某些情况下,当回调参数不安全时(例如 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; }
【讨论】:
boost::any。 :)
holder<ValueType> 模板实例化期间推断的编译时类型。如果是 RTTI,那么您将遇到严重的麻烦,因为 any_cast 会基于 typeid 进行相等匹配,而不是子类匹配,因此实际上不可能将值取回(您必须any_cast 到对象的确切运行时类型,而不是您输入的类型,如果类型是多态的)。我从未使用过boost::any,并且基于对来源的粗略检查,永远不会。太脆弱了。
boost::any 使用 typeid(ValueType),而不是 typeid(value)。因此,即使类型是多态的,它也是纯粹的编译时类型信息。完全没用,不用typeid或任何使用RTTI也能得到同样的效果。
boost::any。