Uma virtual
função pura deve ser implementada em um tipo derivado que será instanciado diretamente, no entanto, o tipo base ainda pode definir uma implementação. Uma classe derivada pode chamar explicitamente a implementação da classe base (se as permissões de acesso permitirem) usando um nome com escopo completo (chamando A::f()
no seu exemplo - se A::f()
fosse public
ou protected
). Algo como:
class B : public A {
virtual void f() {
// class B doesn't have anything special to do for f()
// so we'll call A's
// note that A's declaration of f() would have to be public
// or protected to avoid a compile time problem
A::f();
}
};
O caso de uso em que consigo pensar é quando há um comportamento padrão mais ou menos razoável, mas o designer de classe deseja que esse tipo de comportamento seja invocado apenas explicitamente. Também pode ser o caso em que você deseja que as classes derivadas sempre executem seu próprio trabalho, mas também possam chamar um conjunto comum de funcionalidades.
Observe que, embora seja permitido pela linguagem, não é algo que eu vejo comumente usado (e o fato de que isso pode ser feito parece surpreender a maioria dos programadores de C ++, mesmo os mais experientes).
deported
. (em .inl ou .cpp para se referir a práticas comuns de nomeação de arquivos).Para ser claro, você está entendendo errado o que = 0; depois de uma função virtual significa.
= 0 significa que as classes derivadas devem fornecer uma implementação, não que a classe base não possa fornecer uma implementação.
Na prática, quando você marca uma função virtual como pura (= 0), há muito pouco sentido em fornecer uma definição, porque ela nunca será chamada, a menos que alguém o faça explicitamente via Base :: Function (...) ou se o parâmetro O construtor da classe base chama a função virtual em questão.
fonte
A vantagem disso é que ele força os tipos derivados a ainda substituir o método, mas também fornece uma implementação padrão ou aditiva.
fonte
Se você possui um código que deve ser executado pela classe derivada, mas não deseja que seja executado diretamente - e deseja forçá-lo a ser substituído.
Seu código está correto, apesar de tudo isso não ser um recurso usado com frequência, e geralmente visto apenas ao tentar definir um destruidor virtual puro - nesse caso, você deve fornecer uma implementação. O engraçado é que, depois que você deriva dessa classe, não precisará substituir o destruidor.
Portanto, o uso sensato de funções virtuais puras é especificar um destruidor virtual puro como uma palavra-chave "não final".
O código a seguir está surpreendentemente correto:
fonte
Você teria que dar um corpo a um destruidor virtual puro, por exemplo :)
Leia: http://cplusplus.co.il/2009/08/22/pure-virtual-destructor/
(Link quebrado, usar arquivo)
fonte
Sim isto está correcto. No seu exemplo, as classes derivadas de A herdam a interface f () e uma implementação padrão. Mas você força classes derivadas a implementar o método f () (mesmo que seja apenas para chamar a implementação padrão fornecida por A).
Scott Meyers discute isso no item C ++ eficaz (2ª edição) # 36 Diferencie entre herança da interface e herança da implementação. O número do item pode ter sido alterado na última edição.
fonte
Funções virtuais puras com ou sem um corpo simplesmente significam que os tipos derivados devem fornecer sua própria implementação.
Os corpos puros de funções virtuais na classe base são úteis se suas classes derivadas quiserem chamar sua implementação de classe base.
fonte
O 'virtual void foo () = 0;' sintaxe não significa que você não pode implementar foo () na classe atual, você pode. Isso também não significa que você deve implementá-lo em classes derivadas . Antes de me dar um tapa, vamos observar o problema do diamante: (código implícito, veja bem).
Agora, a invocação obj-> foo () resultará em B :: foo () e depois em C :: bar ().
Você vê ... métodos virtuais puros não precisam ser implementados em classes derivadas (foo () não tem implementação na classe C - o compilador compilará) No C ++, existem muitas brechas.
Espero poder ajudar :-)
fonte
C
no seu exemplo. Você pode instanciar um objeto do tipoD
porque ele obtém sua implementação defoo
fromB
.Um caso de uso importante de ter um método virtual puro com um corpo de implementação é quando você deseja ter uma classe abstrata, mas não possui métodos adequados na classe para torná-la virtual. Nesse caso, você pode tornar o destruidor da classe virtual e colocar a implementação desejada (mesmo um corpo vazio) para isso. Como um exemplo:
Essa técnica torna a
Foo
classe abstrata e, como resultado, impossível instanciar a classe diretamente. Ao mesmo tempo, você não adicionou um método virtual puro adicional para tornar aFoo
classe abstrata.fonte