¿En qué tipo de escenarios declararíamos una función miembro como una "función amiga"? ¿Qué propósito exacto tiene la función amiga que desafía uno de los conceptos centrales de 'Encapsulación' de OOP?¿En qué escenarios se debe declarar a un miembro como un amigo?
Respuesta
Utilizaría una función de amigo por el mismo tipo de razones que utilizaría una clase de amigo, pero en función de un miembro (en lugar de una clase completa). Algunas buenas explicaciones están en this thread.
Si bien las funciones y clases de amigo no infringen la encapsulación, pueden ser útiles en algunos escenarios. Por ejemplo, es posible que desee permitir que un arnés de prueba acceda a las partes internas de la clase para permitirle realizar pruebas de la caja blanca. En lugar de abrir toda la clase al arnés de prueba, podría abrir una función particular que acceda a las partes internas requeridas por el arnés de prueba. Si bien esto aún infringe la encapsulación, es menos riesgoso que abrir toda la clase.
Consulte también this article para obtener más información acerca de las clases y funciones de amigos.
A veces el nivel de protección público/privado/protegido no es suficiente para las situaciones del mundo real. Entonces, damos una pequeña cláusula de salida que ayuda sin tener que hacer que los métodos sean públicamente accesibles.
Yo personalmente uso esto de la misma manera que Java usa el nivel de protección 'Paquete'.
Si tengo una clase en el mismo paquete que necesita acceso consideraré usar friend. Si se trata de una clase en otro paquete, entonces me pregunto por qué esta clase necesita acceso y mira mi diseño.
Ver C++ FAQ Lite:
A veces los amigos son sintácticamente mejor (por ejemplo, en la clase de Fred, funciones friend permiten el parámetro Fred a ser segundo, mientras que los miembros lo requieran ser el primero). Otro buen uso de las funciones de amigo son los operadores aritméticos de infijo binario. Por ejemplo, aComplex + aComplex debe definirse como un amigo en lugar de un miembro si también desea permitir un Flotador + un Complemento (las funciones miembro no permiten la promoción del argumento de la izquierda, ya que eso cambiaría la clase del objeto que está el destinatario de la invocación de la función miembro).
Las funciones y clases de Friend no infringen la encapsulación cuando intenta crear una abstracción o interfaz que debe abarcar físicamente varias clases o funciones de C++. Es por eso que amigo fue inventado.
Esos tipos de casos no aparecen a menudo, pero a veces se ve obligado a implementar una abstracción o interfaz con clases y funciones dispares. El ejemplo clásico es implementar algún tipo de clase de números complejos. A las funciones del operador no miembro se le da amistad a la clase principal de números complejos.
También recuerdo haber hecho esto al programar con CORBA en C++. CORBA me obligó a tener clases separadas para implementar servidores CORBA. Pero para una parte particular de nuestro software, necesitaba casarlos juntos como una sola interfaz. La amistad permitió que estas dos clases trabajaran juntas para proporcionar un servicio sin interrupciones a una parte de nuestro software.
Tener la capacidad de marcar una función de miembro en particular en otra clase como amigo de tu clase puede parecer aún más extraño, pero es solo una forma de controlar la amistad. En lugar de permitir que toda la otra clase "entre" como tu amigo, solo permites el acceso a una de sus funciones miembro. De nuevo, esto no es común, pero muy útil cuando lo necesite.
Un punto que considero relevante: las clases miembro tienen acceso a las partes privadas de la clase contenedora. Esto a veces puede ser una mejor alternativa a "amigo".
class A
{
private:
int b;
public:
class MemberNotFriend {
public:
static void test() {
A a;
a.b = 0;
}
};
};
void test()
{
A::MemberNotFriend::test();
}
Aquí está un ejemplo sencillo, concreto de cómo estoy usando una función amigo:
Tengo un juego en el que cada objeto de sprites almacena su información como la posición X, Y como miembros privados. Sin embargo, deseo separar los objetos del juego de la representación: un objeto de juego no necesita los detalles exactos de cómo se representa. Un objeto del juego solo almacena el estado del juego, y este estado del juego se puede representar de diferentes maneras.
Por lo tanto, la clase de objeto del juego tiene una función de amigo: render(). La función render() se implementa fuera de la clase de objeto del juego, pero puede acceder a las posiciones X, Y posicionar a las entidades según sea necesario para representar el objeto del juego.
- 1. Hacer que un miembro funcione como amigo
- 2. declarar un miembro de funciones de una clase prospectivas declarada como amigo
- 3. ¿Por qué no puedo declarar a un amigo a través de un typedef?
- 4. ¿Cómo declarar un amigo que es miembro de otra clase aún no definida en C++?
- 5. ¿Por qué la función de miembro amigo no se reconoce como plantilla de función automáticamente?
- 6. ¿Qué significa "operador = debe ser un miembro no estático"?
- 7. ¿Cuándo debería preferir las funciones de no amigo no miembro a las funciones de miembro?
- 8. ¿Alguna posibilidad de declarar indexadores en C# como miembro abstracto?
- 9. una clave de clase debe ser declarado cuando se declara un amigo
- 10. ¿Operadores de sobrecarga como función miembro o función no miembro (amigo)?
- 11. ¿Cómo declarar un vector de unique_ptr como miembro de datos de clase?
- 12. ¿Qué significa "error: una referencia de miembro no estático debe ser relativa a un objeto específico"?
- 13. ¿Por qué no puedo cambiar a un miembro privado de una clase de una clase de amigo en un espacio de nombres diferente?
- 14. debe declarar la variable escalar
- 15. C# "debe declarar un cuerpo porque no está marcado como abstracto, externo o parcial"
- 16. Enviar un mensaje a un amigo, me pregunto Javascript API
- 17. ¿Un amigo ve las clases base?
- 18. your.package.namespace - ¿a qué se debe cambiar?
- 19. ¿En qué escenarios usa encapsulación?
- 20. ¿Qué es un miembro variante en C++?
- 21. Al declarar una referencia a una matriz de Ints, ¿por qué debe ser una referencia a un puntero const?
- 22. ¿Por qué no debe tener acceso a un miembro compartido/estático a través de una variable de instancia?
- 23. Intentando explicar el contexto en Android a un amigo
- 24. Visualizar el gráfico de Amigo de un amigo (foaf)
- 25. Anulación del operador C++: ¿por qué se prefiere a un amigo?
- 26. Por qué se prefiere la función de amigo a la función de miembro para el operador <<
- 27. sobrecarga del operador (función de amigo y miembro)
- 28. En Java, cuando una interfaz se extiende a otra, ¿por qué se volvería a declarar un método en una subinterfaz?
- 29. ¿Qué estrategia se debe utilizar al exponer C++ a Lua
- 30. Haciendo un parámetro de plantilla un amigo?
+1 para "no violar". Sin embargo, es inútil en el caso de la mayoría de las clases numéricas como complejas, racionales, ... –