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_INVOKABLE

将此宏应用于成员函数的声明,以允许通过元对象系统调用它们。宏写在返回类型之前,如下例所示:

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是指向 -QObject派生类的指针,则这不是必需的。(dynamic_casting toQObject*会起作用,并且会因为虚拟继承而为您提供正确的 QMetaObject ,但这是不必要的,不太安全且不清楚。)

您实际上不需要类的实例来获取元对象:

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

这是可能的,因为每个类有一个 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 回答