Qual é a ideia geral de um delegado em C ++? O que são, como são usados e para que são usados?
Eu gostaria de aprender sobre eles primeiro de uma forma 'caixa preta', mas um pouco de informação sobre as entranhas dessas coisas também seria ótimo.
Este não é o C ++ mais puro ou limpo, mas noto que a base de código onde trabalho os possui em abundância. Espero entendê-los o suficiente, para que eu possa usá-los e não ter que me aprofundar na horrível horribilidade do modelo aninhado.
Esses dois artigos do The Code Project explicam o que quero dizer, mas não de forma sucinta:
c++
delegates
delegation
SirYakalot
fonte
fonte
delegate
não é um nome comum na linguagem c ++. Você deve adicionar algumas informações à pergunta para incluir o contexto em que você a leu. Observe que, embora o padrão possa ser comum, as respostas podem diferir se você falar sobre delegar em geral ou no contexto da CLI do C ++ ou de qualquer outra biblioteca que possua uma implementação específica de delegado .Respostas:
Você tem um número incrível de opções para obter delegados em C ++. Aqui estão os que me vieram à mente.
Opção 1: functors:
Um objeto de função pode ser criado implementando
operator()
Opção 2: expressões lambda (apenas C ++ 11 )
Opção 3: ponteiros de função
Opção 4: ponteiro para funções-membro (solução mais rápida)
Consulte Delegado rápido do C ++ (no The Code Project ).
Opção 5: std :: function
(ou
boost::function
se sua biblioteca padrão não a suportar). É mais lento, mas é o mais flexível.Opção 6: ligação (usando std :: bind )
Permite definir alguns parâmetros com antecedência, conveniente para chamar uma função de membro, por exemplo.
Opção 7: modelos
Aceite qualquer coisa, desde que corresponda à lista de argumentos.
fonte
std::bind
, e ambos realmente fazem a mesma coisa, exceto que lambdas não são polimórficos no sentido de que podem aceitar diferentes tipos de argumentos.binding
na minha lista). Você não pode conseguir isso com ponteiros de função.Um delegado é uma classe que envolve um ponteiro ou referência a uma instância do objeto, um método membro da classe desse objeto a ser chamado nessa instância do objeto e fornece um método para acionar essa chamada.
Aqui está um exemplo:
fonte
Execute()
que aciona a chamada de função no objeto que o delegado envolve.A necessidade de implementações de delegado em C ++ é um constrangimento duradouro para a comunidade C ++. Todos os programadores de C ++ gostariam de tê-los, portanto, eles eventualmente os usam, apesar dos fatos de que:
std::function()
usa operações de heap (e está fora de alcance para programação incorporada séria).Todas as outras implementações fazem concessões em relação à portabilidade ou conformidade padrão em graus maiores ou menores (verifique por meio da inspeção das várias implementações delegadas aqui e no projeto de código). Ainda estou para ver uma implementação que não usa wild reinterpret_casts, classe aninhada "protótipos" que, esperançosamente, produzem ponteiros de função do mesmo tamanho que o passado pelo usuário, truques do compilador como o primeiro a declarar para a frente e, em seguida, typedef declara novamente, desta vez herdando de outra classe ou técnicas obscuras semelhantes. Embora seja uma grande conquista para os implementadores que construíram isso, ainda é um triste testemunho de como o C ++ evolui.
Raramente é apontado que, agora com mais de 3 revisões padrão do C ++, os delegados não foram abordados adequadamente. (Ou a falta de recursos de idioma que permitem implementações simples de delegado.)
Com a maneira como as funções lambda do C ++ 11 são definidas pelo padrão (cada lambda possui um tipo diferente e anônimo), a situação só melhorou em alguns casos de uso. Mas, para o caso de uso do uso de delegados nas APIs da biblioteca (DLL), somente lambdas ainda não são utilizáveis. A técnica comum aqui é primeiro empacotar o lambda em uma função std :: e depois passá-lo pela API.
fonte
std::function
não sempre alocar dinamicamenteMuito simplesmente, um delegado fornece funcionalidade de como um ponteiro de função DEVE trabalhar. Existem muitas limitações de ponteiros de função no C ++. Um delegado usa alguma desagradabilidade de modelo nos bastidores para criar uma coisa de tipo de ponteiro de função da classe de modelo que funciona da maneira que você deseja.
ie - você pode configurá-los para apontar para uma determinada função e pode distribuí-los e chamá-los quando e onde quiser.
Existem alguns exemplos muito bons aqui:
fonte
Uma opção para delegados em C ++ que não é mencionado aqui é fazê-lo no estilo C usando uma função ptr e um argumento de contexto. Esse é provavelmente o mesmo padrão que muitos que estão fazendo essa pergunta estão tentando evitar. Mas, o padrão é portátil, eficiente e utilizável em código incorporado e de kernel.
fonte
Windows Runtime equivalente a um objeto de função no C ++ padrão. Pode-se usar toda a função como parâmetro (na verdade, esse é um ponteiro de função). É usado principalmente em conjunto com eventos. O delegado representa um contrato que os manipuladores de eventos cumprem muito. Facilita como um ponteiro de função pode funcionar.
fonte