La palabra clave friend permite a una función o a otra clase tener acceso a los miembros privados y protegidos de la clase donde se declara friend. Las funciones friend pueden ser tanto globales como métodos de otras clases. Esta construcción permite implementar funciones que requieren acceso al estado interno de una clase, pero que lógicamente no están relacionadas con la interfaz de esa clase.
Se recomienda usar friend:
Advertencia:
Ejemplo:
class Box { int width; public: Box(int w): width(w) {} friend void printWidth(const Box &b); }; void printWidth(const Box &b) { std::cout << b.width << std::endl; }
Pregunta: ¿Puede ser una función friend virtual?
Respuesta común: Sí, porque friend es un modificador de función.
Respuesta correcta: No, las funciones friend no pueden ser virtuales, ¡porque no son miembros de la clase!
Ejemplo:
class Example { friend virtual void foo(); // Error de compilación: virtual no se aplica a friend };
Historia: Al diseñar una biblioteca de matrices, se hicieron todos los operadores aritméticos funciones friend para acelerar, pero se olvidaron del soporte de la constancia y abrieron en exceso el acceso a miembros privados. Más tarde surgió un problema: en el proyecto, otras funciones cambiaron accidentalmente el estado interno de Matrix.
Historia: En un sistema corporativo, las clases auxiliares se convirtieron en friends entre sí para compartir acceso a miembros privados. Esto llevó a dependencias cíclicas: agregar una nueva función requería cambiar todas las clases relacionadas. La posterior refactorización tomó semanas.
Historia: Para pruebas cerradas, se decidió hacer que una clase de prueba fuera friend de la clase de producción. Cuando aparecieron varios conjuntos de pruebas unitarias, rastrear qué métodos privados realmente se usaban se volvió imposible; las pruebas comenzaron a depender de la implementación interna, lo que llevó a un mantenimiento complicado del código.