我有一个继承自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;
//}
}
但这并没有向我展示任何添加的方法,因为方法偏移量等于方法计数,为什么可以呢?我没理由,谢谢你的帮助。
答案 0 :(得分:5)
您需要为Q_INVOKABLE
中要查看的每种方法使用QMetaObject
宏。
<强> Q_INVOKABLE 强>
将此宏应用于成员函数的声明,以允许通过元对象系统调用它们。宏在返回类型之前写入,如以下示例所示:
class Window : public QWidget { Q_OBJECT public: Window(); void normalMethod(); Q_INVOKABLE void invokableMethod(); };
使用Q_INVOKABLE标记invokableMethod()函数,使其在元对象系统中注册,并使用QMetaObject :: invokeMethod()调用它。由于normalMethod()函数未以这种方式注册,因此无法使用QMetaObject :: invokeMethod()调用它。
您还可以使用slots
宏。我认为Q_INVOKABLE
可能会更小。
QMetaObject只知道信号,插槽,属性和其他可调用的成员函数,有时候称为“元方法”作为一个组。
另外,对于你的例子的第一行,你应该(可能)只是调用
const QMetaObject *metaobj = someClass->metaObject();
这不仅仅是化妆品。 dynamic_cast
会将类型检查移动到运行时,如果您在编译时知道someClass
是指向QObject
派生类的指针,则不需要这样做。 (dynamic_cast
到QObject*
将起作用,并且由于虚拟继承而将为您提供正确的QMetaObject,但这是不必要的,不太安全且不清楚。)
您实际上并不需要该类的实例来获取元对象:
const QMetaObject *metaobj = SomeClass::staticMetaObject();
这是可能的,因为每个类有一个QMetaObject,而不是每个对象。
对于想要了解更多关于元对象系统的人,我推荐咖啡和documentation。通常您不需要直接处理QMetaObject实例,除非您正在编写脚本引擎或同样的“meta”。很容易无意中重复Qt已经提供的功能。
此外,Q_DECLARE_METATYPE
不是您想要的。
答案 1 :(得分:2)
the official docs中存在某种歧义。
首先我们看到:
method()和methodCount()提供有关类的信息 元方法(信号,槽和其他可调用的成员函数)。
但后来:
int QMetaObject :: methodCount()const返回的方法数 这个类,包括每个基地提供的属性数量 类。这些包括信号和插槽以及普通成员 功能
但实际上我们无法通过Qt MetaObject System访问“普通”方法。
因此,要访问您的方法,您应该使用Q_INVOKABLE
宏声明它们:
Q_INVOKABLE void method1();
Q_INVOKABLE void method2();