测试一个类是否是多态的
我们有一个子项目commonUtils",其中包含在整个父项目中使用的许多通用代码片段.我看到的这样一个有趣的东西是:-
We have a sub-project 'commonUtils' that has many generic code-snippets used across the parent project. One such interesting stuff i saw was :-
/*********************************************************************
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
*********************************************************************/
template <class T>
bool isPolymorphic() {
bool answer=false;
typeid(answer=true,T());
return answer;
}
我相信评论并认为它是一个非常有趣的模板,尽管它不是在整个项目中使用.我只是出于好奇而尝试这样使用它...
I believed the comment and thought that it is quite an interesting template though it is not used across the project. I tried using it like this just for curiosity ...
class PolyBase {
public:
virtual ~PolyBase(){}
};
class NPolyBase {
public:
~NPolyBase(){}
};
if (isPolymorphic<PolyBase>())
std::cout<<"PolyBase = Polymorphic
";
if (isPolymorphic<NPolyBase>())
std::cout<<"NPolyBase = Also Polymorphic
";
但是这些都没有返回 true.MSVC 2005 未给出警告,但 Comeau 警告 typeid 表达式无效.C++ 标准中的第 5.2.8 节没有像注释所说的那样说任何东西,即 typeid 在编译时对非多态类型进行评估,在运行时对多态类型进行评估.
But none of those ever returns true. MSVC 2005 gives no warnings but Comeau warns typeid expression has no effect. Section 5.2.8 in the C++ standard does not say anything like what the comment says i.e. typeid is is evaluated at compile time for non-polymorphic types and at runtime for polymorphic types.
1) 所以我猜这个评论是误导/完全错误的,或者因为这段代码的作者是一位相当资深的 C++ 程序员,我错过了什么吗?
1) So i guess the comment is misleading/plain-wrong or since the author of this code is quite a senior C++ programmer, am i missing something?
2) OTOH,我想知道我们是否可以使用某种技术来测试一个类是否是多态的(至少具有一个虚函数)?
2) OTOH, I am wondering if we can test whether a class is polymorphic(has at least one virtual function) using some technique?
3) 什么时候想知道一个类是否是多态的?胡乱猜测;使用 dynamic_cast
获取类的起始地址(因为 dynamic_cast
仅适用于多态类).
3) When would one want to know if a class is polymorphic? Wild guess; to get the start-address of a class by using dynamic_cast<void*>(T)
(as dynamic_cast
works only on polymorphic classes).
等待您的意见.
提前致谢,
推荐答案
我无法想象如何使用 typeid 来检查类型是多态的.它甚至不能用来断言它是,因为 typeid 将适用于任何类型.Boost here 有一个实现.至于为什么它可能是必要的――我知道的一种情况是 Boost.Serialization 库.如果您要保存非多态类型,那么您可以保存它.如果保存多态类型,则必须使用 typeid 获取其动态类型,然后调用该类型的序列化方法(在某个表中查找).
I cannot imagine any possible way how that typeid could be used to check that type is polymorphic. It cannot even be used to assert that it is, since typeid will work on any type. Boost has an implementation here. As for why it might be necessary -- one case I know is the Boost.Serialization library. If you are saving non-polymorphic type, then you can just save it. If saving polymorphic one, you have to gets its dynamic type using typeid, and then invoke serialization method for that type (looking it up in some table).
更新:看来我真的错了.考虑这个变体:
Update: it appears I am actually wrong. Consider this variant:
template <class T>
bool isPolymorphic() {
bool answer=false;
T *t = new T();
typeid(answer=true,*t);
delete t;
return answer;
}
正如名称所暗示的那样,这实际上确实有效,完全符合您原始代码片段中的注释.如果 typeid 内的表达式没有指定多态类类型的左值"(std 3.2/2),则不会评估它.因此,在上述情况下,如果 T 不是多态的,则不会计算 typeid 表达式.如果 T 是多态的,那么 *t 确实是多态类型的左值,所以必须对整个表达式求值.
This actually does work as name suggests, exactly per comment in your original code snippet. The expression inside typeid is not evaluated if it "does not designate an lvalue of polymorphic class type" (std 3.2/2). So, in the case above, if T is not polymorphic, the typeid expression is not evaluated. If T is polymorphic, then *t is indeed lvalue of polymorphic type, so entire expression has to be evaluated.
现在,您原来的示例仍然是错误的 :-).它使用 T()
,而不是 *t
.并且 T()
创建 rvalue (std 3.10/6).所以,它仍然会产生一个不是多态类的左值"的表达式.
Now, your original example is still wrong :-). It used T()
, not *t
. And T()
create rvalue (std 3.10/6). So, it still yields an expression that is not "lvalue of polymorphic class".
这是相当有趣的把戏.另一方面,它的实际价值有些有限――因为 boost::is_polymorphic 给你一个编译时常量,这个给你一个运行时值,所以你不能为多态和非多态类型实例化不同的代码.
That's fairly interesting trick. On the other hand, its practical value is somewhat limited -- because while boost::is_polymorphic gives you a compile-time constant, this one gives you a run-time value, so you cannot instantiate different code for polymorphic and non-polymorphic types.
相关文章