Ouvi dizer que os modelos de função de membro da classe C ++ não podem ser virtuais. Isso é verdade?
Se eles podem ser virtuais, qual é o exemplo de um cenário em que alguém usaria essa função?
c++
templates
virtual-functions
function-templates
c++-faq
WannaBeGeek
fonte
fonte
Respostas:
Os modelos são todos sobre o compilador que gera código em tempo de compilação . As funções virtuais são sobre o sistema de tempo de execução, descobrindo qual função chamar no tempo de execução .
Depois que o sistema de tempo de execução descobriu que precisaria chamar uma função virtual de modelo, a compilação está concluída e o compilador não pode mais gerar a instância apropriada. Portanto, você não pode ter modelos de função de membro virtual.
No entanto, existem algumas técnicas poderosas e interessantes decorrentes da combinação de polimorfismo e modelos, principalmente o chamado apagamento de tipo .
fonte
Virtual functions are all about the run-time system figuring out which function to call at run-time
- desculpe, mas esta é uma maneira bastante errada e bastante confusa. É apenas uma indireção e não há um "tempo de execução" envolvido, é sabido durante o tempo de compilação que a função a ser chamada é aquela apontada pelo n-ésimo ponteiro na tabela. "Descobrir" implica que há verificações de tipo e coisas do tipo, o que não é o caso.Once the run-time system figured out it would need to call a templatized virtual function
- se a função é virtual ou não, é conhecida no momento da compilação.void f(concr_base& cb, virt_base& vb) { cb.f(); vb.f(); }
, "saberão" qual função é chamada no pontocb.f()
chamado e não sabem dissovb.f()
. O último deve ser descoberto em tempo de execução , pelo sistema de tempo de execução . Se você deseja chamar isso de "descobrir" e se é mais ou menos eficiente, isso não muda um pouco esses fatos.Dos modelos C ++ O guia completo:
fonte
O C ++ não permite funções de membro de modelo virtual no momento. O motivo mais provável é a complexidade de implementá-lo. Rajendra dá uma boa razão para que isso não possa ser feito no momento, mas isso pode ser possível com alterações razoáveis do padrão. Especialmente, descobrir quantas instanciações de uma função modelada realmente existem e a criação da tabela v parece difícil se você considerar o local da chamada da função virtual. As pessoas de padrões apenas têm muitas outras coisas para fazer no momento e o C ++ 1x também é muito trabalhoso para os escritores de compiladores.
Quando você precisaria de uma função de membro modelada? Uma vez me deparei com uma situação em que tentei refatorar uma hierarquia com uma classe base virtual pura. Era um estilo ruim para implementar estratégias diferentes. Eu queria mudar o argumento de uma das funções virtuais para um tipo numérico e, em vez de sobrecarregar a função membro e substituir toda sobrecarga em todas as subclasses, tentei usar funções de modelo virtual (e descobri que elas não existem .)
fonte
Tabelas de funções virtuais
Vamos começar com algumas informações sobre as tabelas de funções virtuais e como elas funcionam ( fonte ):
Meu problema, ou como eu vim aqui
Estou tentando usar algo parecido com isso agora para uma classe base de cubefile com funções de carregamento otimizadas, que serão implementadas de maneira diferente para diferentes tipos de cubos (alguns armazenados por pixel, outros por imagem etc.).
Algum código:
O que eu gostaria que fosse, mas não será compilado devido a uma combinação de modelos virtual:
Acabei movendo a declaração do modelo para o nível da classe. Essa solução teria forçado os programas a saber sobre tipos específicos de dados que liam antes de lê-los, o que é inaceitável.Solução
aviso, isso não é muito bonito, mas me permitiu remover o código de execução repetitiva
1) na classe base
2) e nas aulas infantis
Observe que LoadAnyCube não está declarado na classe base.
Aqui está outra resposta de estouro de pilha com uma solução alternativa : precisa de uma solução alternativa para um membro de modelo virtual .
fonte
O código a seguir pode ser compilado e executado corretamente, usando o MinGW G ++ 3.4.5 na Janela 7:
e a saída é:
E depois adicionei uma nova classe X:
Quando tentei usar a classe X em main () assim:
g ++ relate o seguinte erro:
Portanto, é óbvio que:
fonte
Não, eles não podem. Mas:
tem o mesmo efeito se tudo o que você quer fazer é ter uma interface comum e adiar a implementação para subclasses.
fonte
Foo
ponteiro está qualificado comoFoo<Bar>
, não pode apontar para umFoo<Barf>
ouFoo<XXX>
.Não, as funções de membro do modelo não podem ser virtuais.
fonte
Nas outras respostas, a função de modelo proposta é uma fachada e não oferece nenhum benefício prático.
A linguagem não permite funções de modelo virtual, mas com uma solução alternativa é possível ter ambas, por exemplo, uma implementação de modelo para cada classe e uma interface comum virtual.
No entanto, é necessário definir para cada combinação de tipo de modelo uma função de invólucro virtual fictício:
Resultado:
Experimente aqui
fonte
Para responder à segunda parte da pergunta:
Isso não é uma coisa irracional a se querer fazer. Por exemplo, Java (onde todos os métodos são virtuais) não tem problemas com métodos genéricos.
Um exemplo em C ++ de querer um modelo de função virtual é uma função membro que aceita um iterador genérico. Ou uma função membro que aceita um objeto de função genérico.
A solução para esse problema é usar o tipo apagamento com a função boost :: any_range e boost ::, que permitirá aceitar um iterador ou um functor genérico sem a necessidade de transformar sua função em um modelo.
fonte
Existe uma solução alternativa para o 'método de modelo virtual' se um conjunto de tipos para o método de modelo for conhecido antecipadamente.
Para mostrar a ideia, no exemplo abaixo, apenas dois tipos são usados (
int
edouble
).Lá, um método de modelo 'virtual' (
Base::Method
) chama o método virtual correspondente (um dosBase::VMethod
) que, por sua vez, chama a implementação do método de modelo (Impl::TMethod
).Só é necessário implementar o método de modelo
TMethod
em implementações derivadas (AImpl
,BImpl
) e usoDerived<*Impl>
.Resultado:
NB:
Base::Method
é realmente excedente para código real (VMethod
pode ser tornado público e usado diretamente). Eu o adicionei para que pareça um método de modelo 'virtual' real.fonte
Base
classe original toda vez que precisar chamar uma função de modelo com um tipo de argumento não compatível com os implementados até agora. Evitar essa necessidade é a intenção de modelos ...Embora uma pergunta mais antiga que tenha sido respondida por muitos, acredito que um método sucinto, não tão diferente dos outros publicados, seja usar uma macro menor para ajudar a facilitar a duplicação de declarações de classe.
Então agora, para implementar nossa subclasse:
O benefício aqui é que, ao adicionar um tipo recém-suportado, tudo isso pode ser feito a partir do cabeçalho abstrato e renunciar possivelmente a retificá-lo em vários arquivos de origem / cabeçalho.
fonte
Pelo menos com as funções virtuais do gcc 5.4, podem ser membros de modelos, mas devem ser eles próprios.
Saídas
fonte
Tente o seguinte:
Escreva em classeder.h:
Verifique, se estiver trabalhando com isso, para escrever este código em main.cpp:
fonte