Digamos que tenho este sinal:
signals:
void progressNotification(int progress);
Eu só aprendi recentemente sobre a palavra-chave emit no Qt. Até agora, eu costumava executar sinais apenas chamando-os como uma função normal. Então, em vez de:
emit progressNotification(1000 * seconds);
Eu escreveria:
progressNotification(1000 * seconds);
Chamá-los assim parecia funcionar, e todos os slots conectados seriam executados, então usar a palavra-chave emit causa um comportamento diferente ou é apenas um açúcar sintático?
emit
não é necessário. É estranho, porém, que você aprendeuemit
muito depois de chamar sinais diretamente, já que o sistema de slots de sinal é uma das primeiras coisas a serem aprendidas sobre o Qt.Respostas:
emit
é apenas açúcar sintático. Se você olhar para a saída pré-processada da função que emite um sinal, verá queemit
simplesmente desapareceu.A "mágica" acontece no código gerado para a função de emissão de sinal, que você pode examinar inspecionando o código C ++ gerado pelo moc.
Por exemplo, um
foo
sinal sem parâmetros gera esta função-membro:E o código
emit foo();
é pré-processado para simplesmentefoo();
emit
é definido emQt/qobjectdefs.h
(pelo menos no tipo de código aberto da fonte), assim:(Definir guarda é para permitir que você use Qt com outros frameworks que têm nomes
no_keywords
conflitantes por meio da opção de configuração do QMake.)fonte
emit
que realmente fez mais do que nada? Eu acho que ter o 'açúcar sintático' neste caso apenas confunde o novato (ou pelo menos eu quando eu era um usuário novato do Qt) - parece que algo mágico ou importante está acontecendo com aemit
pseudo-palavra-chave, quando ela não faz nada em all - toda a mágica acontece em uma função antiga regular quemoc
cria (moc
é a mágica para sinais e slots Qt).emit
é uma decoração desnecessária que nada mais faz senão parecer importante.emit
diz à pessoa que está lendo a chamada que a mágica está para acontecer (ou seja, isso vai acionar o código em objetos dos quais essa classe potencialmente nunca ouviu falar e essas chamadas podem ser síncronas ou assíncronas), que é essencialmente totalmente perdido se você omitir a palavra-chave. Use-o. É autodocumentado. "Novatos" devem ler documentos e tutoriais eemit
estão sempre lá (pelo menos nos documentos oficiais). Descobrir que você pode simplesmente chamar a função deve acontecer depois de "ver a luz" - você não é mais um novato nesse ponto.emit
'palavra-chave'. Acho que teria preferido que uma convenção de nomenclatura fosse usada se fosse necessário deixar claro que uma chamada de função é um sinal.emit
.emit
comentário de palavra-chave-psuedo fosse deixar claro que um sinal está sendo invocado, então uma convenção de nomenclatura poderia fazer o mesmo, sem mistério e com benefícios semelhantes. A convenção de nomenclatura não poderia ser imposta pelo Qt (na verdade,moc
poderia aplicá-la - mas não estou defendendo isso também), mas o Qt não pode impor o uso deemit
qualquer um deles. E embora você possa 'desligar'emit
se houver conflito de nomes, isso não ajuda muito se você tiver um monte de arquivos de origem que o estão usando (desnecessariamente, para inicializar).Após 18 meses ... comecei com comentários sob a resposta de @Mat e estava ficando sem espaço rapidamente. Portanto, a resposta.
IMO
emit
não é açúcar sintático nem uma palavra-chave simples no sentido de queconnect
mecanismo a reconhecer que de fato é umsignal
, eTodo o sistema de sinal / slot é um idioma diferente de uma simples chamada de função. Acredito que decorra do padrão do observador. Há também uma grande diferença entre a
signal
e aslot
: um sinal não precisa ser implementado, mas um slot deve ser !Você está andando na rua e vê uma casa pegando fogo (um sinal). Você disca 911 ( conecta o sinal de incêndio com o slot de resposta do 911 ). O sinal foi apenas emitido , enquanto o slot foi implementado pelo corpo de bombeiros. Pode ser impreciso, mas essa é a ideia. Vejamos o exemplo do OP.
Algum objeto de back-end sabe quanto progresso foi feito. Portanto, poderia simplesmente
emit progressNotification(...)
sinalizar. Cabe à classe que exibe a barra de progresso real, captar esse sinal e executá-lo. Mas como a visualização se conecta a esse sinal? Bem-vindo ao sistema de sinal / slot do Qt. Agora, pode-se conceber uma classe de gerenciador (normalmente um tipo de widget), que consiste em um objeto de visualização e um objeto de computação de dados (ambos sendoQObjects
)connect (m_myDataEngine, &DataEngine::progressNotification, m_myViewObj, &SimpleView::displayProgress)
.Não vamos entrar nos aspectos de design da classe de gerenciador, mas basta dizer que é aqui que o sistema de sinal / slot se destaca. Posso me concentrar em projetar uma arquitetura muito limpa para meu aplicativo. Nem sempre, mas muitas vezes, acho que apenas emito sinais, mas implemento slots .
Se for possível usar / chamar um método de sinal sem nunca emiti-lo , isso necessariamente implica que você nunca precisou dessa função como um sinal em primeiro lugar.
fonte
emit
verdade é apenas uma macro vazia e puramente opcional. Não são assim as palavras-chavesignal
eslot
que são processadas pelo moc.signal
é usado para fornecer a implementação da função,slot
é usado para criar a entrada de metaobjeto para que seja encontrado com aSLOT(MySlot())
macro ou em QML.emit
é suggar sintático. Nada jamais reclamará se você escreveremit i++;
(mas talvez seus colegas de trabalho) e ainda não conseguir se conectari++
.A segunda opção implicaria que você sempre sabe qual é o nome da função e os parâmetros da função e que o objeto para o qual você está enviando é conhecido por aquela função específica. Esses dois casos nem sempre são verdadeiros, então essas são as duas principais razões pelas quais slots e sinais foram criados. "por baixo do capô", o mecanismo de sinal e slot é apenas uma tabela com indicadores para cada função conectada.
Além disso, veja este pdf que explica muito claramente a natureza dos sinais e mecanismo de slots: http://www.elpauer.org/stuff/a_deeper_look_at_signals_and_slots.pdf
fonte
emit
era apenas um ambiente autônomo. Mas, mesmo neste caso, a leitura do corpo da pergunta deveria ter esclarecido as coisas, então -1.