문제

I've got some kind of object factory (template based), that works pretty good for my purposes. But now I've tried to work with class, that derives from both QObject and pure abstract class (interface) and I've got strange run-time errors.

Here the simple picture of this class (Derived)

class Interface  {
public:
    Interface(){}
    virtual ~Interface(){}    
    virtual int getResult() = 0;
};

class Derived : public QObject, public Interface {
    Q_OBJECT
public:
    explicit Derived(QObject *parent = 0);        
    int getResult();        
}; 

and its implementation in derived.cpp:

#include "derived.h"    
Derived::Derived(QObject *parent)
    : QObject(parent) {
}    
int Derived::getResult() {
    return 55;
}

When I try to cast void pointer to the Interface, I'll get unexpected (for me) behavior, it can be or runtime error, or other method call (it depends of classes' size).

#include "derived.h"    
void * create() {
    return new Derived();
}

int main(int argc, char *argv[]) {
    Interface * interface = reinterpret_cast<Interface *>(create());    
    int res = interface->getResult(); // Run-time error, or other method is called here
    return 0;
}

Could you explain me why I cannot cast void pointer to interface? And is there any workaround?

Thanks for your responses

도움이 되었습니까?

해결책

Reinterpreting a pointer to a derived class as a pointer to a base class gives undefined behaviour. This is highlighted by multiple inheritance: since there is more than one base class, and the two base subobjects must have different addresses, they can't both have the same address as the derived object. So the pointer returned by your create function points to a Derived, but not necessarily to the Interface subobject. It could point to QObject subobject, or to neither.

The best option is to return Derived* or Interface* from your function; if it must be void* for some reason, then the only well-defined cast you can make is back to Derived*, which can then be converted to Interface* using standard conversions.

By using void* you have thrown away all static and dynamic knowledge of the type; the only way to restore that information is to cast back to the correct type.

다른 팁

Mixing reinterpret_cast with multiple inheritance will likely cause all kinds of problems. In your case, the void* will probably point to the QObject part of the Derived, not the Interface part.

It would probably work better with a dynamic_cast, which can adjust the pointer to point to the correct subobject of the derived class.

Note that in general, the need for these types of casts are a sign of bad design. In your specific case, your factory function needs to return an Interface*. void* in C++ where no C interfacing is involved is just unnecessary and bad.

Apart from all this, factory functions are something of a Java thing, and only required when applying strict design methodology, which often adds more fluff than contributing to clean and bug-free code.

If that doesn't cut it, you'll want dynamic_cast. In Qt for QObjects, you can see if qobject_cast has any merit in your situation.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top