我听过很多人说任何使用typeid都是糟糕的设计,但对我来说似乎它提供了很好的实用性.
typeid"糟糕的设计"?typeid可接受?Nic*_*las 18
问题不在于typeid.问题是看到typeid会鼓励你写这个:
PolymorphicType *pType = ...;
if(typeid(*pType) == typeid(Derived1))
pType->Func1();
else if(typeid(*pType) == typeid(Derived2))
pType->Func2();
else if(typeid(*pType) == typeid(Derived3))
pType->Func3();
Run Code Online (Sandbox Code Playgroud)
这就是我们所说的"非常愚蠢".这是以尽可能最不合理的方式完成的虚函数调用.typeid在用于替换dynamic_cast和virtual运行时有可能被滥用.
这个例子可能听起来很牵强.毕竟,很明显这只是一个虚拟电话.但是,糟糕的代码通常会从阻力最小的路径发展而来; 所需要的只是一个人做一个typeid() == typeid(),这个代码的种子已经开始了.一般来说,如果你typeid经常直接使用,你可能会做其他语言结构更好的事情.
typeid是最后的多态类型推导方法.
所有用法都typeid错了吗?当然不是.boost::any没有它就不可能.那么它是可能的,但它不会比任何更安全void*.typeid是什么使类型安全boost::any型擦除成为可能.还有其他合法用途.
但是在代码行与使用比率方面,我建议它最多应该在10,000行代码中.比这少得多,你可能错了.
类型检查是否缓慢?
通常,调用的主要原因typeid是模板化代码(如在boost::any)中或者当您期望多态类型时.如果类型是静态确定的(即:给出了非多态类型的类型名称或值),那么您可以期望它在编译时完成.
这是你应该关注的多态值.我见过一个性能测试表明,部分typeid实现实际行走的类层次结构,因此它需要为他们找到类型的时间是成正比的实际类型和给定类型之间的类的数量.每个实现都会有所不同,但这是一个很好的指示,也许你不应该把它放在性能关键代码中.
我认为没有人说使用typeid本身就是糟糕的设计; 相反,你会听到是那种用法typeid是表示糟糕的设计.这个想法存在着区分(比如说)的任何逻辑Square从Circle实际上应该是在那些类,所以应该由一个虚函数(多态性)来表示.
不用说,这不是一个绝对的规则.
可惜那些给你这个好建议的人却无法给出理由。这意味着他们是简单的货物崇拜程序员。
所有表达式都有静态编译时类型(模板扩展后)。所有类型要么是多态的,要么不是。
我将尝试为您详细说明为什么typeid(最接近)在这两种情况下都是无用的:
typeid当表达式的静态类型不是多态时,没有理由使用它。编译器将使用静态类型,而不是动态类型,因此编译时函数重载有效。使用模板化类型特征(例如is_same.
如果表达式的静态类型是多态的,则typeid失败。是的,它将提供有关对象的动态类型的信息。但仅限于最派生的动态类型。这违反了里氏替换原则,因为给定类型Base和,添加派生自的Child新类型将不会被按原样处理。开闭原则也被违反,因为如果不重写所有内容,就无法使用新类型扩展设计。没有封装,因为有关类层次结构的信息必须分散在整个程序中,从而产生强耦合。 克服了其中一些但不是全部问题。GrandchildChildChilddynamic_cast
总之,一个使用的程序typeid将很难维护和测试。
而且,与任何规则一样,可能存在有限的例外。您使用 OO 语言的继承和虚函数功能,但实际上并不需要多态设计。我可以想到一个:您想要将类型名称记录为字符串,使用type_info::name(). 您也许还可以使用它来检测切片(其中已经违反了多态性)。但这仅适用于调试,而不适用于控制程序流程。
| 归档时间: |
|
| 查看次数: |
6063 次 |
| 最近记录: |