O que a macro Q_OBJECT faz? Por que todos os objetos Qt precisam dessa macro?

131

Comecei a usar o Qt e notei que todas as definições de classe de exemplo têm a macro Q_OBJECTcomo primeira linha. Qual é o objetivo dessa macro de pré-processador?

Trevor Boyd Smith
fonte
25
QT refere-se ao QuickTime e Qt refere-se à biblioteca C ++ chamada Qt.
Bleadof 03/09/09

Respostas:

132

Da documentação Qt :

O Meta-Object Compiler, moc, é o programa que lida com as extensões C ++ do Qt.

A ferramenta moc lê um arquivo de cabeçalho C ++. Se encontrar uma ou mais declarações de classe que contenham a macro Q_OBJECT, ele produzirá um arquivo de origem C ++ contendo o código de metaobjeto para essas classes. Entre outras coisas, o código de metaobjeto é necessário para o mecanismo de sinais e slots, as informações sobre o tipo de tempo de execução e o sistema de propriedades dinâmicas.

Stu Mackellar
fonte
por que não preciso escrever explicitamente, Q_OBJECT::connect()mas apenas connect()?
mLstudent33
19

Simplesmente informa ao pré-compilador que esta classe possui elementos de GUI e precisa ser executada através do 'moc'; você só precisa adicioná-lo às classes que usam o mecanismo de sinal / slot.
Mas será silenciosamente ignorado em qualquer outra classe - apenas aumenta o tempo de compilação.

Martin Beckett
fonte
3
Também é falso que você só precise dele em classes que usam o mecanismo de sinal / slot. A ausência de Q_OBJECTquebra a qobject_castintrospecção. Isso pode levar a um comportamento desconcertante, por isso é uma má ideia.
Restabeleça Monica
2
Não é verdade que Q_OBJECTserá "silenciosamente" ignorado em outras QObjectclasses (não ). De acordo com o padrão C ++, ele introduz um comportamento indefinido, declarando várias funções de membro e variáveis ​​que nunca são definidas. Também polui o espaço de nomes da sua classe com QObjectmembros -específicos. Por exemplo, a Q_OBJECTpode muito bem quebrar uma classe não relacionada que contém um método chamado metaObject.
Restabeleça Monica
2
Isto é errado. Embora você provavelmente deseje equipar a maioria das classes de gui com a Q_OBJECTmacro, faz sentido ter classes sem gui com a macro, bem como classes sem a macro. A macro é útil, mas não se limita a, nem é exigida, por gui-classes.
61318 pasbi
9

O MOC (compilador de objetos meta) converte os arquivos de cabeçalho incluídos na macro Q_OBJECT em código-fonte equivalente a C ++. Ele basicamente controla o mecanismo do slot de sinal e o torna compreensível para o compilador C ++

aditya
fonte
2
Isso é falso: a Q_OBJECTmacro é expandida pelo compilador, o moc não é necessário para isso. O moc não faz nada com a macro em si, mas gera as definições das variáveis ​​de membro e métodos que a Q_OBJECTmacro declarou .
Restabeleça Monica
5

1 Da documentação Qt do sistema Meta-Object

A ferramenta moc lê um arquivo de origem C ++. Se encontrar uma ou mais declarações de classe que contenham a macro Q_OBJECT, ele produzirá outro arquivo de origem C ++ que contém o código de metaobjeto para cada uma dessas classes. Este arquivo de origem gerado é # incluído no arquivo de origem da classe ou, mais geralmente, compilado e vinculado à implementação da classe.

2 Da documentação Qt de THE Q_OBJECT

A macro Q_OBJECT deve aparecer na seção privada de uma definição de classe que declare seus próprios sinais e slots ou que use outros serviços fornecidos pelo sistema de meta objetos do Qt.

3 Da documentação Qt do moc

A ferramenta moc lê um arquivo de cabeçalho C ++. Se encontrar uma ou mais declarações de classe que contenham a macro Q_OBJECT, ele produzirá um arquivo de origem C ++ contendo o código de metaobjeto para essas classes. Entre outras coisas, o código de metaobjeto é necessário para o mecanismo de sinais e slots, as informações sobre o tipo de tempo de execução e o sistema de propriedades dinâmicas.

4 Da documentação Qt de sinais e slots

A macro Q_OBJECT é expandida pelo pré-processador para declarar várias funções de membro implementadas pelo moc; se você receber erros de compilador ao longo das linhas de "referência indefinida à vtable para LcdNumber", provavelmente esqueceu de executar o moc ou incluir a saída moc no comando link.

Bob Zhang
fonte
2

No gcc, -Evocê pode ver macros expandidas. É isso que se Q_OBJECTexpande no gcc no Linux. Esteja ciente de que isso pode depender da plataforma e pode mudar dependendo da versão do QT. Você pode ver que não é apenas uma tag para o compilador 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 {};
Arne
fonte
0

A macro Q_OBJECT deve aparecer na seção privada de uma definição de classe que declare seus próprios sinais e slots ou que use outros serviços fornecidos pelo sistema de meta objetos do Qt.

Andres
fonte
1
Isso é enganoso: a Q_OBJECTmacro deve aparecer em todas as classes derivadas QObject. Seu código será sutilmente quebrado quando a macro estiver ausente, e apenas porque acontece a compilação não a torna correta.
Restabeleça Monica
@KubaOber, você tem um exemplo de código que compila, mas não funciona quando a Q_OBJECTmacro está ausente?
Chris
2
Se você observar a implementação de Q_OBJECT, descobrirá que ele usa especificadores de acesso. Então, se a macro deve aparecer no sob a private, protectedou publicespecificadores é irrelevante - é apenas uma convenção para colocá-lo à frente da classe.
precisa saber é o seguinte