How to check if an object implements an interface

I want to implement custom behavior for certain objects.

To do this, let my objects (inheriting from QGraphicsItem) implement some interface.

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

From the outside, I thought I was just doing

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

Unfortunately, this is a failure ... usually ... therefore I created a flag for verification, and if the flag was true, then only dared to drop it.

But I kept thinking, he should not fail. So I became bold and tried again, this time at QWidget. Instead of a crash, I got

 QWidget::insertAction: Attempt to insert null action 

This is an if(item1 == NULL) test that gives this message ...

How to check if my element SomeInterface ?

Note: item cannot be null.

+7
c ++ inheritance multiple-inheritance qt
source share
3 answers

There may be a compiler that disables runtime information, in which case this explains the behavior. Otherwise, item1 must not be null if dynamic_cast worked

+1
source share

A simple general template can make the code more understandable and simple to implement.

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

You need a second function template to avoid trying to call function2 for a class that does not implement it. if you try this:

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

in a class that does not implement function2, the compiler will be balk, because it cannot bind to function2 for this instance, and it is correct, but not intuitive, because it looks like it will not be called from logic from left to right. However, the compiler cannot know at compile time what isSomeInterface will return.

This method is not considered by many to be a "good style" of programming, because it can lead to C ++ spiking and bloat code, and it becomes difficult to maintain and debug. dynamic_cast usually used to differentiate functions with the same name in the class hierarchy, in particular, for methods of the base class and subclass, and in the case of multiple inheritance with overlapping method signatures, to accurately select the correct method for this circumstance.

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

- A macro to check if the interface is consistent at run time, if necessary. However, use sparingly. If you do this more than once over time, your code most likely needs to be refactored.

0
source share

How about something simple:

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

And returns another int for user behavior?

-2
source share