Buscar..


Introducción

Las clases bien diseñadas encapsulan su funcionalidad, ocultan su implementación y proporcionan una interfaz limpia y documentada. Esto permite un nuevo diseño o cambio siempre que la interfaz no se modifique.

En un escenario más complejo, pueden requerirse múltiples clases que dependen de los detalles de implementación de cada uno. Las clases y funciones de Friend permiten a estos compañeros acceder a los detalles de los demás, sin comprometer la encapsulación y el ocultamiento de la información de la interfaz documentada.

Función de amigo

Una clase o una estructura puede declarar cualquier función que sea amiga. Si una función es un amigo de una clase, puede acceder a todos sus miembros protegidos y privados:

// Forward declaration of functions.
void friend_function();
void non_friend_function();

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
private:
    int private_value;
    // Declare one of the function as a friend.
    friend void friend_function();
};

void non_friend_function() {
    PrivateHolder ph(10);
    // Compilation error: private_value is private.
    std::cout << ph.private_value << std::endl;
}

void friend_function() {
    // OK: friends may access private values.
    PrivateHolder ph(10);
    std::cout << ph.private_value << std::endl;
}

Los modificadores de acceso no alteran la semántica de los amigos. Las declaraciones públicas, protegidas y privadas de un amigo son equivalentes.

Las declaraciones de amigos no se heredan. Por ejemplo, si subclase PrivateHolder :

class PrivateHolderDerived : public PrivateHolder {
public:
    PrivateHolderDerived(int val) : PrivateHolder(val) {}
private:
    int derived_private_value = 0;
};

y tratar de acceder a sus miembros, obtendremos lo siguiente:

void friend_function() {
    PrivateHolderDerived pd(20);
    // OK.
    std::cout << pd.private_value << std::endl;
    // Compilation error: derived_private_value is private.
    std::cout << pd.derived_private_value << std::endl;
}

Tenga en cuenta que la función miembro PrivateHolderDerived no puede acceder a PrivateHolder::private_value , mientras que la función friend puede hacerlo.

Método de amigo

Los métodos pueden declararse como amigos, así como funciones:

class Accesser {
public:
    void private_accesser();
};

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
    friend void Accesser::private_accesser();
private:
    int private_value;
};

void Accesser::private_accesser() {
    PrivateHolder ph(10);
    // OK: this method is declares as friend.
    std::cout << ph.private_value << std::endl;
}

Clase de amigo

Una clase entera puede ser declarada como amiga. La declaración de clase de amigo significa que cualquier miembro del amigo puede acceder a miembros privados y protegidos de la clase declarante:

class Accesser {
public:
    void private_accesser1();
    void private_accesser2();
};

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
    friend class Accesser;
private:
    int private_value;
};

void Accesser::private_accesser1() {
    PrivateHolder ph(10);
    // OK.
    std::cout << ph.private_value << std::endl;
}

void Accesser::private_accesser2() {
    PrivateHolder ph(10);
    // OK.
    std::cout << ph.private_value + 1 << std::endl;
}

La declaración de la clase amiga no es reflexiva. Si las clases necesitan acceso privado en ambas direcciones, ambas necesitan declaraciones de amigos.

class Accesser {
public:
    void private_accesser1();
    void private_accesser2();
private:
    int private_value = 0;
};

class PrivateHolder {
public:
    PrivateHolder(int val) : private_value(val) {}
    // Accesser is a friend of PrivateHolder
    friend class Accesser;
    void reverse_accesse() {
        // but PrivateHolder cannot access Accesser's members.
        Accesser a;
        std::cout << a.private_value;
    }
private:
    int private_value;
};


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow