Estou tendo problemas para entender a nova sintaxe de sinal / slot (usando o ponteiro para a função de membro) no Qt 5, conforme descrito em Nova sintaxe do slot de sinal . Eu tentei mudar isso:
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
para isso:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
mas recebo um erro ao tentar compilá-lo:
error: nenhuma função correspondente para chamada para
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
Eu tentei com clang e gcc no Linux, ambos com -std=c++11
.
O que estou fazendo de errado e como corrigi-lo?
Respostas:
O problema aqui é que existem dois sinais com esse nome:
QSpinBox::valueChanged(int)
eQSpinBox::valueChanged(QString)
. No Qt 5.7, existem funções auxiliares para selecionar a sobrecarga desejada, para que você possa escreverPara o Qt 5.6 e versões anteriores, você precisa dizer ao Qt qual deseja escolher, convertendo-o para o tipo certo:
Eu sei, é feio . Mas não há maneira de contornar isso. A lição de hoje é: não sobrecarregue seus sinais e slots!
Adendo : o que é realmente irritante no elenco é que
void
(para sinais).Então, às vezes, eu me encontrei usando esse trecho do C ++ 11:
Uso:
Pessoalmente, acho que não é realmente útil. Espero que esse problema desapareça quando o Creator (ou seu IDE) inserir automaticamente a conversão correta ao concluir automaticamente a operação de tirar o PMF. Mas enquanto isso ...
Nota: a sintaxe de conexão baseada em PMF não requer C ++ 11 !
Adendo 2 : no Qt 5.7, foram adicionadas funções auxiliares para atenuar isso, modeladas após a minha solução alternativa acima. O ajudante principal é
qOverload
(você também temqConstOverload
eqNonConstOverload
).Exemplo de uso (dos documentos):
Adendo 3 : se você olhar para a documentação de qualquer sinal de sobrecarga, agora a solução para o problema de sobrecarga está claramente definida nos próprios documentos. Por exemplo, https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 diz
fonte
static_cast
feiúra do que a sintaxe antiga, simplesmente porque a nova sintaxe permite uma verificação em tempo de compilação da existência do sinal / slot em que a sintaxe antiga falharia em tempo de execução.QSerialPort
)A mensagem de erro é:
A parte importante disso é a menção do " tipo de função sobrecarregada não resolvida ". O compilador não sabe se você quer dizer
QSpinBox::valueChanged(int)
ouQSpinBox::valueChanged(QString)
.Existem várias maneiras de resolver a sobrecarga:
Forneça um parâmetro de modelo adequado para
connect()
Isso força
connect()
a resolver&QSpinBox::valueChanged
a sobrecarga que leva umint
.Se você tiver sobrecargas não resolvidas para o argumento do slot, precisará fornecer o segundo argumento do modelo
connect()
. Infelizmente, não há sintaxe para solicitar que o primeiro seja inferido; portanto, você precisará fornecer os dois. É quando a segunda abordagem pode ajudar:Use uma variável temporária do tipo correto
A atribuição para
signal
selecionará a sobrecarga desejada e agora pode ser substituída com sucesso no modelo. Isso funciona igualmente bem com o argumento 'slot', e acho menos complicado nesse caso.Use uma conversão
Podemos evitar
static_cast
aqui, pois é simplesmente uma coerção, em vez de remover as proteções da linguagem. Eu uso algo como:Isso nos permite escrever
fonte
Na verdade, você pode apenas envolver seu slot com lambda e isto:
ficará melhor. : \
fonte
As soluções acima funcionam, mas eu resolvi isso de uma maneira um pouco diferente, usando uma macro. Portanto, caso esteja aqui:
Adicione isso no seu código.
Então, seu exemplo:
Torna-se:
fonte
#define CONNECTCAST(class,fun,args) static_cast<void(class::*)args>(&class::fun)
- usado comoCONNECTCAST(QSpinBox, valueChanged, (double))
neste caso.