Я не могу получить методы из QMetaObject, методы offset и count равны

у меня есть класс, который наследует от 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

Решение

Вам нужно использовать 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_castв QObject* будет работать и даст вам правильный QMetaObject из-за виртуального наследования, но это не нужно, менее безопасно и неясно.)

Вам на самом деле не нужен экземпляр класса, чтобы получить мета-объект:

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

Это возможно, потому что есть один QMetaObject на класс, а не на объект.

Для тех, кто хочет узнать больше о мета-объектной системе, я рекомендую кофе и документация. Обычно вам не нужно напрямую иметь дело с экземплярами QMetaObject, если только вы не пишете механизм сценариев или что-то в этом роде «мета». Легко непреднамеренно дублировать функциональность, которую уже предоставляет Qt.


Также, Q_DECLARE_METATYPE это не то, что вы хотите.

5

Другие решения

Существует некоторая неопределенность в официальные документы.

Сначала мы видим:

method () и methodCount () предоставляют информацию о классе
мета-методы (сигналы, слоты и др. invokable функции-члены).

Но позже:

int QMetaObject :: methodCount () const Возвращает количество методов в
этот класс, включая количество свойств, предоставляемых каждой базой
учебный класс. Они включают в себя сигналы и слоты, а также нормальный член
функции.

Но на самом деле мы не можем получить доступ к «нормальным» методам через систему Qt MetaObject.

Итак, чтобы получить доступ к вашим методам, вы должны объявить их с Q_INVOKABLE макрос:

Q_INVOKABLE void method1();
Q_INVOKABLE void method2();
2

По вопросам рекламы [email protected]