测试类是否是多态的 [英] Test whether a class is polymorphic

查看:135
本文介绍了测试类是否是多态的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个子项目commonUtils,在父项目中使用了许多通用代码片段。
我看到的一个有趣的东西是: -

  / ************ **************************************************** ******* 
如果T是多态的,编译器需要在运行时评估typeid
stuff,并且答案将为true。如果T是非多态的,
编译器需要在编译时评估typeid的东西,
whence的答案将保持为false
************* **************************************************** ****** /
template< class T>
bool isPolymorphic(){
bool answer = false;
typeid(answer = true,T());
return answer;
}

我相信评论,并认为这是一个有趣的模板,不是
用于整个项目。我尝试使用它只是为了好奇...

 类PolyBase {
public:
virtual 〜PBase(){}
};

class NPloyBase {
public:
〜NBase(){}
};


if(isPolymorphic< PolyBase>())
std :: cout<<PBase = Polymorphic\ n;
if(isPolymorphic< NPolyBase>())
std :: cout<<NBase = Also Polymorphic\

但是这些都没有返回true。 MSVC 2005没有给出警告,但Comeau警告typeid表达式没有效果。 C ++标准中的第5.2.8节没有说什么类似的注释,即typeid是在编译时对非多态类型和运行时对多态类型进行计算。



1)所以我想这个评论是误导/明白错误,或者因为这段代码的作者是一个高级的C ++程序员,我错过了什么?



2 )OTOH,我想知道如果我们可以测试一个类是否是多态的(至少有一个虚拟函数)使用一些技术?



3)什么时候想知道如果一个类是多态的?胡乱猜测;使用 dynamic_cast (如 dynamic_cast 工程来获取类的开始地址





等待您的意见。

$ b

解决方案

我不能想象任何可能的方式如何可以使用typeid检查类型是多态。它甚至不能用于断言它是,因为typeid将工作在任何类型。
Boost有一个实现这里。至于为什么它可能是必要的 - 一个我知道的是Boost.Serialization库。如果你保存非多态类型,那么你可以保存它。如果保存多态性,你必须使用typeid获取其动态类型,然后调用该类型的序列化方法(在某些表中查找它)。



更新:它看来我实际上错了。考虑此变体:

 模板< class T& 
bool 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()创建右值(std 3.10 / 6)。因此,它仍然产生一个不是多态类的左值的表达式。



这是一个很有趣的技巧。另一方面,它的实际价值有点有限 - 因为虽然boost :: is_polymorphic给你一个编译时常量,这一个给你一个运行时间值,所以你不能实例化多态和非多态类型的不同代码。


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 ~PBase(){}
};

class NPloyBase {
public:
   ~NBase(){}
};


if (isPolymorphic<PolyBase>())
  std::cout<<"PBase = Polymorphic\n";
if (isPolymorphic<NPolyBase>())
  std::cout<<"NBase = Also Polymorphic\n";

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) 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, I am wondering if we can test whether a class is polymorphic(has at least one virtual function) using some technique?

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).

Awaiting your opinions.

Thanks in advance,

解决方案

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; 
}

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.

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".

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.

这篇关于测试类是否是多态的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆