¿Cuál es la ventaja de hacer que un método privado sea virtual en C ++?
He notado esto en un proyecto de código abierto C ++:
class HTMLDocument : public Document, public CachedResourceClient {
private:
virtual bool childAllowed(Node*);
virtual PassRefPtr<Element> createElement(const AtomicString& tagName, ExceptionCode&);
};
c++
polymorphism
access-specifier
Silverburgh
fuente
fuente
Respuestas:
Herb Sutter lo ha explicado muy bien aquí .
Pauta # 2: Prefiere hacer privadas las funciones virtuales
Esto permite que las clases derivadas anulen la función para personalizar el comportamiento según sea necesario, sin exponer aún más las funciones virtuales directamente al hacerlas invocables por clases derivadas (como sería posible si las funciones solo estuvieran protegidas). El punto es que existen funciones virtuales para permitir la personalización; a menos que también necesiten ser invocados directamente desde el código de las clases derivadas, no hay necesidad de hacerlos nunca más que privados
fuente
Si el método es virtual, puede ser anulado por clases derivadas, incluso si es privado. Cuando se llama al método virtual, se invocará la versión anulada.
(En oposición a Herb Sutter citado por Prasoon Saurav en su respuesta, C ++ FAQ Lite recomienda contra virtuales privados , principalmente porque a menudo confunde a las personas).
fuente
A pesar de todas las llamadas para declarar privado a un miembro virtual, el argumento simplemente no aguanta. Con frecuencia, la anulación de una función virtual de una clase derivada tendrá que llamar a la versión de la clase base. No puede si se declara
private
:Usted tiene que declarar el método de la clase base
protected
.Luego, debe tomar el desagradable recurso de indicar mediante un comentario que el método debe ser anulado pero no llamado.
Así, la guía # 3 de Herb Sutter ... Pero el caballo está fuera del granero de todos modos.
Cuando declaras algo
protected
, confías implícitamente en el escritor de cualquier clase derivada para que comprenda y use adecuadamente las partes internas protegidas, tal como unafriend
declaración implica una confianza más profunda para losprivate
miembros.Los usuarios que tienen un mal comportamiento al violar esa confianza (por ejemplo, etiquetados como 'despistados' al no molestarse en leer su documentación) solo tienen la culpa.
Actualización : He recibido algunos comentarios que afirman que puede "encadenar" implementaciones de funciones virtuales de esta manera utilizando funciones virtuales privadas. Si es así, me gustaría verlo.
Los compiladores de C ++ que uso definitivamente no permitirán que una implementación de clase derivada llame a una implementación de clase base privada.
Si el comité de C ++ se relajara "privado" para permitir este acceso específico, estaría todo para funciones virtuales privadas. Tal como están las cosas, todavía se nos aconseja cerrar la puerta del establo después de que el caballo sea robado.
fuente
set_data
. Instruccionesm_data = ndata;
y, porcleanup();
lo tanto, podrían considerarse invariantes para todas las implementaciones. Por lo tanto, haga quecleanup()
no sea virtual y privado. Agregue una llamada a otro método privado que sea virtual y el punto de extensión de su clase. Ahora ya no es necesario que sus clases derivadas llamen a la basecleanup()
, su código se mantiene limpio y su interfaz es difícil de usar incorrectamente.cleanup()
s de la cadena, el argumento se desmorona. ¿O está recomendando una función virtual adicional para cada descendiente en la cadena? Ick Incluso Herb Sutter permitió funciones virtuales protegidas como un vacío en su directriz # 3. De todos modos, sin un código real nunca me convencerás.Me encontré con este concepto por primera vez mientras leía '' C ++ eficaz '' de Scott Meyers, Artículo 35: Considere alternativas a las funciones virtuales. Quería hacer referencia a Scott Mayers para otros que puedan estar interesados.
Es parte del patrón de método de plantilla a través del idioma de interfaz no virtual : los métodos de cara al público no son virtuales; más bien, envuelven las llamadas a métodos virtuales que son privadas. La clase base puede ejecutar la lógica antes y después de la llamada a la función virtual privada:
Creo que este es un patrón de diseño muy interesante y estoy seguro de que puede ver cómo es útil el control agregado.
private
? La mejor razón es que ya hemos proporcionado unpublic
método de enfrentamiento.protected
para que pueda usar el método para otras cosas interesantes? Supongo que siempre dependerá de su diseño y de cómo cree que encaja la clase base. Yo diría que el creador de la clase derivada debería centrarse en implementar la lógica requerida; todo lo demás ya está a cargo. Además, está la cuestión de la encapsulación.Desde una perspectiva de C ++, es completamente legítimo anular un método virtual privado a pesar de que no podrá llamarlo desde su clase. Esto es compatible con el diseño descrito anteriormente.
fuente
Los uso para permitir que las clases derivadas "llenen los espacios en blanco" para una clase base sin exponer ese agujero a los usuarios finales. Por ejemplo, tengo objetos altamente dinámicos que se derivan de una base común, que solo puede implementar 2/3 de la máquina de estado general (las clases derivadas proporcionan el 1/3 restante dependiendo de un argumento de plantilla, y la base no puede ser una plantilla para otras razones).
NECESITO tener la clase base común para que muchas de las API públicas funcionen correctamente (estoy usando plantillas variadas), pero no puedo dejar que ese objeto salga a la naturaleza. Peor aún, si dejo los cráteres en la máquina de estado, en forma de funciones virtuales puras, en cualquier lugar que no sea "Privado", permito que un usuario inteligente o despistado derivado de una de sus clases secundarias anule los métodos que los usuarios nunca deberían tocar. Entonces, puse los 'cerebros' de la máquina de estado en funciones virtuales PRIVADAS. Luego, los hijos inmediatos de la clase base llenan los espacios en blanco en sus anulaciones NO virtuales, y los usuarios pueden usar de forma segura los objetos resultantes o crear sus propias clases derivadas adicionales sin preocuparse por estropear la máquina de estado.
En cuanto al argumento de que no deberías TENER métodos virtuales públicos, digo BS. Los usuarios pueden anular incorrectamente los virtuales privados con la misma facilidad que los públicos: después de todo, están definiendo nuevas clases. Si el público no debe modificar una API determinada, no la haga virtual en absoluto en objetos de acceso público.
fuente