5

QObjectから継承するクラスがあり、Q_OBJECTマクロがあります。

class SomeClass: public QObject
{
    Q_OBJECT
public:
    SomeClass(QObject *parent = 0);
    void method1();
    void method2();
    ...
};

同じヘッダーの別のクラスで、そのクラスのインスタンスを作成してから、「SomeClass」からすべてのメソッドを取得してQMapに格納しようとします。

this->someclass = new SomeClass(); // in constructor.

..。

cout<<"init some class methods"<<endl;
    const QMetaObject *metaobj = dynamic_cast<QObject*>(this->someclass)->metaObject();
    cout<<"offset "<<metaobj->methodOffset()<<endl;
    for(int i = metaobj->methodOffset();i < metaobj->methodCount();i++){
        QMetaMethod metamethod = metaobj->method(i);
        //if(metamethod.methodType() == QMetaMethod::Method){
            QString methodname = QString(metamethod.signature());
            methodname = methodname.replace(QRegExp("\\(.*\\)"),"");
            controlmethods.insert(methodname,metamethod);
            cout<<"added method: "<<metamethod.signature()<<" as "<<methodname.toAscii().data()<<endl;
        //}
    }

しかし、これは、メソッドのオフセットがメソッドの数に等しいため、追加されたメソッドを表示しません。なぜそうなるのでしょうか。私は理由がわからない、助けてくれてありがとう。

4

2 に答える 2

6

Q_INVOKABLEで表示するメソッドごとにマクロを使用する必要がありますQMetaObject

ドキュメントから

Q_呼び出し可能

このマクロをメンバー関数の宣言に適用して、メタオブジェクト システム経由で呼び出すことができるようにします。次の例に示すように、マクロは戻り値の型の前に記述されます。

class Window : public QWidget {
    Q_OBJECT

public:
    Window();
    void normalMethod();
    Q_INVOKABLE void invokableMethod(); };

invokableMethod() 関数は Q_INVOKABLE を使用してマークアップされ、メタオブジェクト システムに登録され、QMetaObject::invokeMethod() を使用して呼び出されるようになります。このように normalMethod() 関数は登録されていないため、QMetaObject::invokeMethod() を使用して呼び出すことはできません。

slotsマクロも使えます。Q_INVOKABLEでも、もっと最小限かもしれないと思います。

QMetaObject は、シグナル、スロット、プロパティ、およびその他の呼び出し可能なメンバー関数のみを認識します。グループとして「メタメソッド」と呼ばれることもあります。


また、例の最初の行では、(おそらく)単に呼び出す必要があります

const QMetaObject *metaobj = someClass->metaObject();

これは単なる化粧品ではありません。は、dynamic_cast型チェックをランタイムに移動します。これは、コンパイル時に派生クラスsomeClassへのポインターであることがわかっている場合は必要ありません。QObjectdynamic_casting toQObject*は機能し、仮想継承のために正しい QMetaObject を取得しますが、不要で、安全性が低く、不明確です。)

メタオブジェクトを取得するためにクラスのインスタンスは実際には必要ありません。

const QMetaObject *metaobj = SomeClass::staticMetaObject();

これが可能なのは、オブジェクトごとではなく、クラスごとに 1 つの QMetaObject があるためです。

メタオブジェクト システムについて詳しく知りたい人には、コーヒーと ドキュメントをお勧めします。通常、スクリプト エンジンまたは同等の「メタ」を作成する場合を除き、QMetaObject インスタンスを直接処理する必要はありません。Qt が既に提供している機能を意図せずに複製するのは簡単です。


また、Q_DECLARE_METATYPEあなたが望むものではありません。

于 2013-01-29T07:27:13.983 に答える
2

公式ドキュメントにはある種のあいまいさがあります。

まず、次のことがわかります。

method() および methodCount() は、クラスのメタメソッド (シグナル、スロット、およびその他の呼び出し可能なメンバー関数) に関する情報を提供します。

でもその後:

int QMetaObject::methodCount() const 各基本クラスが提供するプロパティの数を含め、このクラスのメソッドの数を返します。これらには、シグナルとスロット、および通常のメンバー関数が含まれます。

しかし実際には、Qt MetaObject System を介して「通常の」メソッドにアクセスすることはできません。

したがって、メソッドにアクセスするには、Q_INVOKABLEマクロで宣言する必要があります。

Q_INVOKABLE void method1();
Q_INVOKABLE void method2();
于 2013-01-29T07:02:04.143 に答える