La respuesta a por qué colocamos variables miembro privadas en los encabezados de C ++ es que el tamaño de la clase debe conocerse en los puntos donde se declaran las instancias para que el compilador pueda generar código que se mueva apropiadamente sobre la pila.
¿Por qué necesitamos poner miembros privados en encabezados?
Pero, ¿hay alguna razón para declarar funciones privadas en la definición de clase?
La alternativa sería esencialmente el idioma de pimpl pero sin la indirección superflua.
¿Es esta característica del lenguaje más que un error histórico?
Si permitiste agregar métodos a una clase fuera de su definición, cualquiera podría agregarlos en cualquier lugar , en cualquier archivo.
Eso daría de inmediato a todos los códigos de clientes acceso trivial a miembros de datos privados y protegidos.
Una vez que haya terminado la definición de la clase, no hay forma de marcar algunos archivos como especialmente bendecidos por el autor para extenderla, solo hay unidades de traducción planas. Entonces, la única forma razonable de decirle al compilador que un conjunto particular de métodos son oficiales, o bendecidos por el autor de la clase, es declarándolos dentro de la clase.
Tenga en cuenta que tenemos acceso directo a la memoria en C ++, lo que significa que generalmente es trivial crear un tipo de sombra con el mismo diseño de memoria que su clase, agregar mis propios métodos (o simplemente hacer públicos todos los datos) y
reinterpret_cast
. O puedo encontrar el código de su función privada, o desarmarlo. O busque la dirección de la función en la tabla de símbolos y llame o directamente.Estos especificadores de acceso no intentan evitar estos ataques, porque eso no es posible. Solo indican cómo se supone que se debe usar una clase.
fuente
La respuesta aceptada explica esto para las funciones privadas virtuales , pero eso solo responde a una faceta específica de la pregunta, que es considerablemente más limitada de lo que preguntó el OP. Entonces, necesitamos reformular: ¿Por qué estamos obligados a declarar funciones privadas no virtuales en los encabezados?
Otra respuesta invoca el hecho de que las clases deben declararse en un bloque, después de lo cual están selladas y no se pueden agregar. Eso es lo que estaría haciendo al omitir declarar un método privado en el encabezado y luego tratar de definirlo en otro lugar. Buen punto ¿Por qué algunos usuarios de la clase deberían poder aumentarlo de una manera que otros usuarios no puedan observar? Los métodos privados son parte de esto y no están excluidos de esto. Pero luego preguntas por qué están incluidos, y parece un poco tautológico. ¿Por qué los usuarios de clase deben saber sobre ellos? Si no fueran visibles, los usuarios no podrían agregar ninguno, y bueno, listo.
Entonces, quería proporcionar una respuesta que, en lugar de incluir métodos privados por defecto, proporcione puntos específicos a favor de que sean visibles para los usuarios. Se da una razón mecanicista para las funciones privadas no virtuales que requieren declaración pública en GotW # 100 de Herb Sutter sobre el lenguaje Pimpl como parte de su justificación. No hablaré sobre Pimpl aquí, ya que estoy seguro de que todos lo sabemos. Pero aquí está el bit relevante:
Sutter es, por supuesto, una fuente extremadamente confiable como miembro del Comité, por lo que conoce "una decisión de diseño deliberada" cuando la ve. Y la idea de exigir la declaración pública de métodos privados como una forma de evitar una semántica alterada o accesibilidad accidentalmente interrumpida más tarde es probablemente la razón más convincente. Afortunadamente, ¡ya que todo parecía inútil antes de ahora!
fuente
hay dos razones para hacer esto.
Primero, tenga en cuenta que el especificador de acceso es para el compilador y no es relevante en tiempo de ejecución. Acceder a un miembro privado fuera del alcance es un error de compilación .
Concisión
Considere una función que es corta, una o dos líneas. Existe para reducir la replicación de código en otros lugares, lo que también tiene la ventaja de poder cambiar cómo funciona un algoritmo o cualquier otra cosa en un lugar en lugar de muchos (por ejemplo, cambiar un algoritmo de clasificación).
¿Prefieres tener una o dos líneas rápidas en el encabezado, o tener el prototipo de la función allí más una implementación en alguna parte? Es más fácil de encontrar en el encabezado, y para funciones cortas, es mucho más detallado tener una implementación separada.
Hay otra gran ventaja, que es ...
Funciones en linea
Una función privada puede estar en línea, y esto necesariamente requiere que esté en el encabezado. Considera esto:
La función privada puede ser incorporada junto con la función pública. Eso se hace a discreción del compilador, ya que la
inline
palabra clave es técnicamente una sugerencia , no un requisito.fuente
inline
, no hay razón para usar la palabra clave allí..cpp
miembro en el archivo que está en línea por funciones miembro que están definidas fuera de la definición de clase, pero dicha función no sería privada.Otra razón para tener métodos privados en el archivo de encabezado: hay casos en los que un método en línea público no hace mucho más que llamar a uno o varios métodos privados. Tener los métodos privados en el encabezado significa que una llamada al método público puede estar completamente en línea con el código real de los métodos privados, y la alineación no se detiene con una llamada al método privado. Incluso desde una unidad de compilación diferente (y los métodos públicos generalmente se llamarían desde diferentes unidades de compilación).
Por supuesto, también existe la razón de que el compilador no puede detectar problemas con la resolución de sobrecarga si no conoce todos los métodos, incluidos los privados.
fuente
Es para permitir que esas funciones accedan a los miembros privados. De lo contrario, los necesitaría
friend
en el encabezado de todos modos.Si alguna función pudiera acceder a los miembros privados de la clase, privado sería inútil.
fuente