如何正确检查对象是否实现了接口

时间:2015-07-07 17:34:46

标签: c++ qt inheritance multiple-inheritance

我想为某些对象实现自定义行为。

为此,让我的项目(继承自QGraphicsItem)实现一些接口。

class SomeParentItem 
{ 
    SomeParentItem(bool x) { x = true; } 
    void function1() {}
};
class SomeInterface
{
    virtual void function2() = 0;
};
class XYZItem : public QGraphicsXYZItem, public SomeParentItem, public SomeInterface
{
    XYZItem(bool x):SomeParentItem(x) {}
    virtual void function2() { x = false; }
};
class MPQItem : public QGraphicsMPQItem, public SomeParentItem
{
    MPQItem (bool x):SomeParentItem(x) {}
};

从外面看,我以为我只是做

SomeInterface* item1 = dynamic_cast<SomeInterface*>(item);
if(item1 == NULL)
    item->function1(); 
else
    item1->function2();  

不幸的是,这会崩溃...通常......所以我正在创建一个标志来测试,如果标志是真的,那么只有敢于施放。

但我一直在想,它不应该崩溃。所以我勇敢再次尝试,这次是在一个QWidget孩子。而不是崩溃我得到了

QWidget::insertAction: Attempt to insert null action

测试if(item1 == NULL)给出了这个消息......

如果我的项目实现SomeInterface

,如何正确检查

注意:item不能为空。

3 个答案:

答案 0 :(得分:1)

可能有一个编译器开关禁用运行时类型信息,在这种情况下它会解释行为。否则,如果dynamic_cast工作

,则item1应该只是非null

答案 1 :(得分:0)

简单的通用模板可以使代码更易读,更容易实现。

template < class T > 
        bool is_SomeParentItem( T& P)                                                                                                                                                                      
        {                                                                                                                                                                                             
          if ( dynamic_cast<SomeParentItem*>(&P) ) 
              return true;                                                                                                                                             
          else 
              return false;                                                                                                                                                                               
        }

template < class T > 
        bool is_SomeInterface( T& I)                                                                                                                                                                      
        {                                                                                                                                                                                             
          if ( dynamic_cast<SomeInterface*>(&I) ) 
              return true;                                                                                                                                             
          else 
              return false;                                                                                                                                                                               
        }

template < class T >
    void function( T& X)
      {
         if ( isSomeInterface(X) )
         { 
             dynamic_cast<SomeInterface*>(&X)->function2();
             return;
         }

         if ( isSomeParentItem(X) )
             dynamic_cast<SomeParentItem*>(&X)->function1();
      } 

您需要第二个功能模板以避免尝试呼叫 function2在没有实现它的类上。 如果你试试这个:

 if ( isSomeInterface(instance) ) instance.function2(); 

在没有实现function2的类上,编译器会 因为它无法绑定到该实例的function2,所以就是这样 正确但不直观,因为看起来它不会从左到右逻辑调用。但是编译器无法在编译时知道isSomeInterface将返回什么。

许多人认为这种技术不是编程的“好样式”,因为它会导致C ++意大利面条和代码膨胀,并且变得难以维护和调试。 dynamic_cast通常用于区分类层次结构中的同名函数,特别是基类和子类方法,并且在多重继承与方法签名重叠的情况下,坚决选择正确的方法。

    // safe implements                                                                                                                                                                            
#define implements( C, I ) (    __extension__ ({                   \                                                                                                                          
        static bool impl=(dynamic_cast<I*>(&C))? true : false;     \                                                                                                                          
        impl;                                                      \                                                                                                                          
      })) 

     if ( implements( instance, SomeInterface ) ) ...

是一个宏,用于在运行时检查接口合规性(如果需要)。 但是,请谨慎使用。 如果你在很长一段时间内不止一次这样做,你的代码很可能需要重构。

答案 2 :(得分:-2)

如此简单的事情:

class SomeInterface
{
    virtual void function2() = 0;
    virtual qint32 role() =0;
};

为自定义行为返回一个不同的int?