2

ある種のオブジェクトファクトリ(テンプレートベース)があり、それは私の目的にはかなりうまく機能します。しかし今、私はQObjectと純粋な抽象クラス(インターフェース)の両方から派生したクラスを操作しようとしましたが、奇妙な実行時エラーが発生しました。

ここにこのクラスの簡単な図(派生)

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

およびderived.cppでのその実装:

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

voidポインターをインターフェースにキャストしようとすると、予期しない(私にとっては)動作が発生します。これは、実行時エラー、またはその他のメソッド呼び出し(クラスのサイズによって異なります)である可能性があります。

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

voidポインタをインターフェイスにキャストできない理由を教えてください。そして、回避策はありますか?

ご回答ありがとうございます

4

3 に答える 3

3

派生クラスへのポインターを基底クラスへのポインターとして再解釈すると、未定義の動作が発生します。これは多重継承によって強調されます。基本クラスが複数あり、2 つの基本サブオブジェクトは異なるアドレスを持つ必要があるため、両方が派生オブジェクトと同じアドレスを持つことはできません。したがって、create関数によって返されるポインターは を指しますDerivedが、必ずしもInterfaceサブオブジェクトを指すとは限りません。サブオブジェクトを指すことQObjectも、どちらも指すこともできません。

最良のオプションは、関数からDerived*またはInterface*関数を返すことです。void*何らかの理由でそうしなければならない場合、明確に定義された唯一のキャストは に戻すことですDerived*。これは、Interface*標準の変換を使用して に変換できます。

使用void*することで、その型の静的および動的な知識をすべて捨ててしまいます。その情報を復元する唯一の方法は、正しい型にキャストすることです。

于 2013-01-22T13:47:03.503 に答える
1

多重継承と混合reinterpret_castすると、あらゆる種類の問題が発生する可能性があります。あなたの場合、void*はおそらく のQObject部分ではDerivedなく、の部分を指しInterfaceます。

dynamic_cast派生クラスの正しいサブオブジェクトを指すようにポインターを調整できる を使用すると、おそらくよりうまく機能します。

于 2013-01-22T13:46:20.747 に答える
0

一般に、これらのタイプのキャストが必要になるのは、設計が悪いことを示していることに注意してください。特定のケースでは、ファクトリ関数は を返す必要がありますInterface*void*C インターフェースが関与しない C++ では、不必要で悪いことです。

これらすべてとは別に、ファクトリ関数は Java のもののようなものであり、厳密な設計方法論を適用する場合にのみ必要とされます。これは、クリーンでバグのないコードに貢献するよりも多くの綿毛を追加することがよくあります。

それがうまくいかない場合は、 が必要になりdynamic_castます。Qt for QObjects ではqobject_cast、状況にメリットがあるかどうかを確認できます。

于 2013-01-22T13:46:26.563 に答える