Comecei a usar o Qt e notei que todas as definições de classe de exemplo têm a macro Q_OBJECT
como primeira linha. Qual é o objetivo dessa macro de pré-processador?
Comecei a usar o Qt e notei que todas as definições de classe de exemplo têm a macro Q_OBJECT
como primeira linha. Qual é o objetivo dessa macro de pré-processador?
Respostas:
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.
Q_OBJECT::connect()
mas apenas connect()
?
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.
Q_OBJECT
quebra a qobject_cast
introspecção. Isso pode levar a um comportamento desconcertante, por isso é uma má ideia.
Q_OBJECT
será "silenciosamente" ignorado em outras QObject
classes (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 QObject
membros -específicos. Por exemplo, a Q_OBJECT
pode muito bem quebrar uma classe não relacionada que contém um método chamado metaObject
.
Q_OBJECT
macro, 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.
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 ++
Q_OBJECT
macro é 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_OBJECT
macro declarou .
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.
No gcc, -E
você pode ver macros expandidas. É isso que se Q_OBJECT
expande 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 {};
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.
Q_OBJECT
macro 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.
Q_OBJECT
macro está ausente?
Q_OBJECT
, descobrirá que ele usa especificadores de acesso. Então, se a macro deve aparecer no sob a private
, protected
ou public
especificadores é irrelevante - é apenas uma convenção para colocá-lo à frente da classe.