我们有一个子项目'commonUtils',它有许多在父项目中使用的通用代码片段.我看到的一个有趣的东西是: -
/********************************************************************* If T is polymorphic, the compiler is required to evaluate the typeid stuff at runtime, and answer will be true. If T is non-polymorphic, the compiler is required to evaluate the typeid stuff at compile time, whence answer will remain false *********************************************************************/ templatebool isPolymorphic() { bool answer=false; typeid(answer=true,T()); return answer; }
我相信评论并认为它是一个非常有趣的模板,虽然它没有在整个项目中使用.为了好奇,我试着像这样使用它...
class PolyBase { public: virtual ~PolyBase(){} }; class NPolyBase { public: ~NPolyBase(){} }; if (isPolymorphic()) std::cout<<"PolyBase = Polymorphic\n"; if (isPolymorphic ()) std::cout<<"NPolyBase = Also Polymorphic\n";
但这些都没有回归真实.MSVC 2005没有发出警告,但是Comeau警告typeid表达没有任何效果.C++标准中的5.2.8节没有说明评论所说的内容,即在编译时为非多态类型评估typeid,在运行时评估多态类型.
1)所以我认为这个评论是误导/明白错误,或者因为这段代码的作者是一位资深的C++程序员,我错过了什么?
2)OTOH,我想知道我们是否可以使用某种技术测试一个类是否是多态的(至少有一个虚函数)?
3)什么时候想知道一个类是多态的?胡乱猜测; 通过使用获取类的起始地址dynamic_cast
(dynamic_cast
仅适用于多态类).
等待你的意见.
提前致谢,
我无法想象任何可能的方式如何使用typeid来检查该类型是多态的.它甚至不能用来断言它,因为typeid可以在任何类型上工作.Boost 在这里有一个实现.至于为什么可能有必要 - 我知道的一个案例是Boost.Serialization库.如果要保存非多态类型,则只需保存即可.如果保存多态,则必须使用typeid获取其动态类型,然后为该类型调用序列化方法(在某些表中查找).
更新:看来我其实是错的.考虑这个变种:
templatebool isPolymorphic() { bool answer=false; T *t = new T(); typeid(answer=true,*t); delete t; return answer; }
这实际上正如名称所示,确切地说就是原始代码段中的每条评论.如果"不指定多态类类型的左值"(std 3.2/2),则不评估typeid内的表达式.因此,在上面的情况中,如果T不是多态的,则不评估typeid表达式.如果T是多态的,则*t确实是多态类型的左值,因此必须评估整个表达式.
现在,你原来的例子仍然是错的:-).它用过T()
,而不是*t
.并T()
创建rvalue(标准3.10/6).因此,它仍然产生一个不是"多态类的左值"的表达式.
这是一个相当有趣的技巧.另一方面,它的实际价值有些限制 - 因为虽然boost :: is_polymorphic为你提供了一个编译时常量,但是这个给你一个运行时值,所以你不能为多态和非多态类型实例化不同的代码.