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?
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.
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.
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 ++
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 .
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.
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.
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.
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, -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.
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.
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.
Respostas:
Da documentação Qt :
fonte
Q_OBJECT::connect()
mas apenasconnect()
?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.
fonte
Q_OBJECT
quebra aqobject_cast
introspecção. Isso pode levar a um comportamento desconcertante, por isso é uma má ideia.Q_OBJECT
será "silenciosamente" ignorado em outrasQObject
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 comQObject
membros -específicos. Por exemplo, aQ_OBJECT
pode muito bem quebrar uma classe não relacionada que contém um método chamadometaObject
.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 ++
fonte
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 aQ_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.
fonte
No gcc,
-E
você pode ver macros expandidas. É isso que seQ_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.fonte
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.
fonte
Q_OBJECT
macro deve aparecer em todas as classes derivadasQObject
. 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 aprivate
,protected
oupublic
especificadores é irrelevante - é apenas uma convenção para colocá-lo à frente da classe.