Я тільки почав використовувати Qt і помітив, що всі приклади визначень класу мають макрос Q_OBJECT
як перший рядок. Яке призначення цього макроса препроцесора?
Я тільки почав використовувати Qt і помітив, що всі приклади визначень класу мають макрос Q_OBJECT
як перший рядок. Яке призначення цього макроса препроцесора?
Відповіді:
З документації Qt :
Meta-Object Compiler, moc, - це програма, яка обробляє розширення C ++ Qt.
Інструмент moc зчитує файл заголовка C ++. Якщо він знайде одну або більше декларацій класу, які містять макрос Q_OBJECT, він створює вихідний файл C ++, що містить код мета-об'єкта для цих класів. Крім усього іншого, мета-об'єктний код необхідний для механізму сигналів і слотів, інформації про тип часу виконання та динамічної системи властивостей.
Q_OBJECT::connect()
а просто просто connect()
?
Попередньому компілятору це просто говорить про те, що у цього класу є елементи gui і його потрібно запустити через 'moc', вам потрібно лише додати це до класів, які використовують механізм сигнал / слот.
Але це буде тихо ігноровано в будь-яких інших класах - це просто додає часу на збирання.
Q_OBJECT
перерв qobject_cast
і самоаналіз. Це може призвести до деякого здивованого поведінки, тому це погана ідея.
Q_OBJECT
"тихо" буде ігноровано в будь-яких інших (не QObject
) класах. Відповідно до стандарту C ++, він вводить невизначену поведінку, оголошуючи кілька функцій-членів та змінних, які ніколи не визначаються. Він також забруднює простір імен вашого класу QObject
-видовими членами. Наприклад, a Q_OBJECT
може цілком зламати неспоріднений клас, який, як правило, містить метод, який називається metaObject
.
Q_OBJECT
макросом, має цілком сенс мати не-gui-класи з макросом, а також gui-класи без макросу. Макрос корисний, але не обмежений і не потрібен для gui-класів.
MOC (компілятор мета-об'єктів) перетворює файли заголовків, що містять макрос Q_OBJECT, у вихідний код C ++. Він в основному керує механізмом слотового сигналу і робить його зрозумілим компілятору C ++
Q_OBJECT
макрос розширюється компілятором, moc для цього не потрібен. Moc нічого не робить із самим макросом, але він генерує визначення змінних членів та методів, які Q_OBJECT
макрос оголосив .
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 вихід у команду посилання.
У 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 {};
Макрос Q_OBJECT повинен з'являтися в приватному розділі визначення класу, який оголошує власні сигнали та слоти або використовує інші сервіси, що надаються метаоб'єктом системи Qt.
Q_OBJECT
макрос повинен з’являтися в кожному класі, який походить QObject
. Ваш код буде тонко порушений, коли макрос відсутній, і лише тому, що трапляється компіляція, це не робить його нормальним.
Q_OBJECT
макрос відсутній?
Q_OBJECT
, то побачите, що вона використовує специфікатори доступу. Так чи макрос повинен з'явитися в під private
, protected
або public
специфікатор не має ніякого відношення - це просто умовність , щоб помістити його в голові класу.