Qual é a vantagem de tornar virtual um método privado em C ++?
Eu notei isso em um projeto C ++ de código aberto:
class HTMLDocument : public Document, public CachedResourceClient {
private:
virtual bool childAllowed(Node*);
virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
};
c++
polymorphism
access-specifier
Silverburgh
fonte
fonte
Respostas:
Herb Sutter explicou muito bem aqui .
Diretriz 2: Prefira tornar as funções virtuais privadas.
Isso permite que as classes derivadas substituam a função para personalizar o comportamento, conforme necessário, sem expor ainda mais as funções virtuais, tornando-as invocáveis por classes derivadas (como seria possível se as funções fossem apenas protegidas). O ponto é que as funções virtuais existem para permitir a personalização; a menos que eles também precisem ser invocados diretamente do código das classes derivadas, não há necessidade de torná-las nada além de privadas
fonte
Se o método for virtual, ele poderá ser substituído por classes derivadas, mesmo que seja privado. Quando o método virtual é chamado, a versão substituída será chamada.
(Ao contrário de Herb Sutter citado por Prasoon Saurav em sua resposta, o C ++ FAQ Lite recomenda contra virtuais virtuais , principalmente porque muitas vezes confunde as pessoas.)
fonte
Apesar de todas as chamadas para declarar um membro virtual privado, o argumento simplesmente não é válido. Freqüentemente, a substituição de uma função virtual por uma classe derivada precisará chamar a versão da classe base. Não pode se for declarado
private
:Você precisa declarar o método da classe base
protected
.Então, você deve tomar o feio expediente de indicar, por meio de um comentário, que o método deve ser substituído, mas não chamado.
Assim, a diretriz 3 de Herb Sutter ... Mas o cavalo está fora do estábulo de qualquer maneira.
Quando você declara algo
protected
que está implicitamente confiando no escritor de qualquer classe derivada para entender e usar adequadamente os internos protegidos, da mesma maneira que umafriend
declaração implica em uma confiança mais profunda para osprivate
membros.Os usuários que têm mau comportamento por violar essa confiança (por exemplo, rotulados como 'sem noção' por não se preocuparem em ler sua documentação) são os únicos culpados.
Atualizar : recebi alguns comentários que afirmam que você pode "encadear" implementações de funções virtuais dessa maneira usando funções virtuais privadas. Se sim, com certeza gostaria de vê-lo.
Os compiladores C ++ que eu uso definitivamente não permitem que uma implementação de classe derivada chame uma implementação de classe base privada.
Se o comitê C ++ relaxasse "private" para permitir esse acesso específico, eu seria totalmente a favor de funções virtuais privadas. Como está, ainda estamos sendo aconselhados a trancar a porta do celeiro depois que o cavalo for roubado.
fonte
set_data
. Instruçõesm_data = ndata;
e,cleanup();
portanto, pode ser considerado invariável, que deve ser válido para todas as implementações. Torne, portanto,cleanup()
não virtual e privado. Adicione uma chamada a outro método privado virtual e o ponto de extensão da sua classe. Agora não há mais necessidade de suas classes derivadas chamarem a basecleanup()
, seu código permanece limpo e sua interface é difícil de usar incorretamente.cleanup()
s na cadeia, o argumento se desfaz. Ou você está recomendando uma função virtual extra para cada descendente da cadeia? Ick. Até Herb Sutter permitiu funções virtuais protegidas como uma brecha em sua diretriz nº 3. De qualquer forma, sem um código real, você nunca vai me convencer.Encontrei esse conceito pela primeira vez ao ler o 'Effective C ++' de Scott Meyers, item 35: considere alternativas às funções virtuais. Eu queria fazer referência a Scott Mayers para outros que possam estar interessados.
Faz parte do padrão do método de modelo através do idioma da interface não virtual : os métodos voltados para o público não são virtuais; em vez disso, eles agrupam as chamadas de método virtual que são privadas. A classe base pode executar a lógica antes e depois da chamada da função virtual privada:
Acho que esse é um padrão de design muito interessante e tenho certeza de que você pode ver como o controle adicionado é útil.
private
? A melhor razão é que já fornecemos umpublic
método de enfrentamento.protected
lo simplesmente para que eu possa usar o método para outras coisas interessantes? Suponho que sempre dependerá do seu design e de como você acredita que a classe base se encaixa. Eu diria que o criador da classe derivada deve se concentrar na implementação da lógica necessária; tudo o resto já está resolvido. Além disso, há a questão do encapsulamento.Da perspectiva do C ++, é completamente legítimo substituir um método virtual privado, mesmo que você não possa chamá-lo da sua classe. Isso suporta o design descrito acima.
fonte
Eu os uso para permitir que as classes derivadas "preencham os espaços em branco" para uma classe base sem expor esse buraco aos usuários finais. Por exemplo, tenho objetos altamente stateful derivados de uma base comum, que só pode implementar 2/3 da máquina de estado geral (as classes derivadas fornecem o 1/3 restante, dependendo do argumento do modelo, e a base não pode ser um modelo para outras razões).
EU PRECISO ter a classe base comum para fazer com que muitas APIs públicas funcionem corretamente (estou usando modelos variados), mas não posso deixar esse objeto sair para a natureza. Pior, se eu deixar as crateras na máquina de estado - na forma de funções virtuais puras - em qualquer lugar, exceto em "Privado", permito que um usuário inteligente ou sem noção derivado de uma de suas classes filho substitua os métodos que os usuários nunca devem tocar. Então, eu coloquei 'cérebros' da máquina de estado em funções virtuais PRIVADAS. Em seguida, os filhos imediatos da classe base preenchem os espaços em branco em suas substituições NÃO virtuais, e os usuários podem usar com segurança os objetos resultantes ou criar suas próprias classes derivadas adicionais sem se preocupar em estragar a máquina de estado.
Quanto ao argumento de que você não deve ter métodos virtuais públicos, digo BS. Os usuários podem substituir indevidamente os virtuais privados tão facilmente quanto os públicos - eles estão definindo novas classes, afinal. Se o público não deve modificar uma determinada API, não a torne virtual em objetos acessíveis ao público.
fonte