Що робить макрос Q_OBJECT? Чому всім об'єктам Qt потрібен цей макрос?


131

Я тільки почав використовувати Qt і помітив, що всі приклади визначень класу мають макрос Q_OBJECTяк перший рядок. Яке призначення цього макроса препроцесора?


25
QT посилається на QuickTime, а Qt - на бібліотеку C ++ під назвою Qt.
Bleadof

Відповіді:


132

З документації Qt :

Meta-Object Compiler, moc, - це програма, яка обробляє розширення C ++ Qt.

Інструмент moc зчитує файл заголовка C ++. Якщо він знайде одну або більше декларацій класу, які містять макрос Q_OBJECT, він створює вихідний файл C ++, що містить код мета-об'єкта для цих класів. Крім усього іншого, мета-об'єктний код необхідний для механізму сигналів і слотів, інформації про тип часу виконання та динамічної системи властивостей.


чому мені не потрібно чітко писати, Q_OBJECT::connect()а просто просто connect()?
mLstudent33

19

Попередньому компілятору це просто говорить про те, що у цього класу є елементи gui і його потрібно запустити через 'moc', вам потрібно лише додати це до класів, які використовують механізм сигнал / слот.
Але це буде тихо ігноровано в будь-яких інших класах - це просто додає часу на збирання.


3
Також помилково, що вам це потрібно лише в класах, які використовують механізм сигнал / слот. Відсутність Q_OBJECTперерв qobject_castі самоаналіз. Це може призвести до деякого здивованого поведінки, тому це погана ідея.
Відновіть Моніку

2
Неправда, що Q_OBJECT"тихо" буде ігноровано в будь-яких інших (не QObject) класах. Відповідно до стандарту C ++, він вводить невизначену поведінку, оголошуючи кілька функцій-членів та змінних, які ніколи не визначаються. Він також забруднює простір імен вашого класу QObject-видовими членами. Наприклад, a Q_OBJECTможе цілком зламати неспоріднений клас, який, як правило, містить метод, який називається metaObject.
Відновіть Моніку

2
Це неправильно. Хоча ви, мабуть, хочете оснастити більшість gui-класів Q_OBJECTмакросом, має цілком сенс мати не-gui-класи з макросом, а також gui-класи без макросу. Макрос корисний, але не обмежений і не потрібен для gui-класів.
пасбі

9

MOC (компілятор мета-об'єктів) перетворює файли заголовків, що містять макрос Q_OBJECT, у вихідний код C ++. Він в основному керує механізмом слотового сигналу і робить його зрозумілим компілятору C ++


2
Це помилково: Q_OBJECTмакрос розширюється компілятором, moc для цього не потрібен. Moc нічого не робить із самим макросом, але він генерує визначення змінних членів та методів, які Q_OBJECTмакрос оголосив .
Відновіть Моніку

5

1 З документації Qt системи Meta-Object

Інструмент moc читає вихідний файл C ++. Якщо він знайде одну або кілька декларацій класу, що містять макрос Q_OBJECT, він створює інший вихідний файл C ++, який містить код мета-об'єкта для кожного з цих класів. Цей згенерований вихідний файл або # include'd у вихідний файл класу, або, як правило, компілюється та пов'язується з реалізацією класу.

2 З документації Qt THE Q_OBJECT

Макрос Q_OBJECT повинен з'являтися в приватному розділі визначення класу, який оголошує власні сигнали та слоти або використовує інші сервіси, що надаються метаоб'єктом системи Qt.

3 З Qt документації moc

Інструмент moc зчитує файл заголовка C ++. Якщо він знайде одну або більше декларацій класу, які містять макрос Q_OBJECT, він створює вихідний файл C ++, що містить код мета-об'єкта для цих класів. Крім усього іншого, мета-об'єктний код необхідний для механізму сигналів і слотів, інформації про тип часу виконання та динамічної системи властивостей.

4 З документації Qt про сигнали та слоти

Макрос Q_OBJECT розширений препроцесором для оголошення декількох функцій-членів, реалізованих moc; якщо ви отримуєте помилки компілятора в рядках "невизначеної посилання на vtable для LcdNumber", ви, напевно, забули запустити moc або включити moc вихід у команду посилання.


2

У gcc з -Eвами можна побачити розширені макроси. Це те, що Q_OBJECTрозширюється на gcc в Linux. Пам'ятайте, що це може залежати від платформи і може змінюватися залежно від версії QT. Ви можете бачити, що це не лише тег для компілятора moc.

# 11 "mainwindow.hh"
#pragma GCC diagnostic push
# 11 "mainwindow.hh"

# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wsuggest-override"
# 11 "mainwindow.hh"
    static const QMetaObject staticMetaObject; virtual const QMetaObject *metaObject() const; virtual void *qt_metacast(const char *); virtual int qt_metacall(QMetaObject::Call, int, void **); static inline QString tr(const char *s, cons
t char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } __attribute__ ((__deprecated__)) static inline QString trUtf8(const char *s, const char *c = nullptr, int n = -1) { return staticMetaObject.tr(s, c, n); } private:
# 11 "mainwindow.hh"
#pragma GCC diagnostic ignored "-Wattributes"
# 11 "mainwindow.hh"
    __attribute__((visibility("hidden"))) static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
# 11 "mainwindow.hh"
#pragma GCC diagnostic pop
# 11 "mainwindow.hh"
    struct QPrivateSignal {};

0

Макрос Q_OBJECT повинен з'являтися в приватному розділі визначення класу, який оголошує власні сигнали та слоти або використовує інші сервіси, що надаються метаоб'єктом системи Qt.


1
Це вводить в оману: Q_OBJECTмакрос повинен з’являтися в кожному класі, який походить QObject. Ваш код буде тонко порушений, коли макрос відсутній, і лише тому, що трапляється компіляція, це не робить його нормальним.
Відновіть Моніку

@KubaOber У вас є приклад коду, який компілюється, але не працює, коли Q_OBJECTмакрос відсутній?
Кріс

2
Якщо ви подивитесь на реалізацію програми Q_OBJECT, то побачите, що вона використовує специфікатори доступу. Так чи макрос повинен з'явитися в під private, protectedабо publicспецифікатор не має ніякого відношення - це просто умовність , щоб помістити його в голові класу.
TrebledJ
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.