In C++, encapsulation restricts external access to private and protected members. However, certain scenarios require external functions or other classes to interact with these internal details. The friend keyword provides a mechanism to grant specific external entities privileged access to otherwise restricted class members.
Global Functions as Friends
A non-member function can be designated as a friend to access private and protected members of a class. This declaration appears in side the class definition using the friend keyword, typically placed in the public or private section with out affecting visibility.
#include <iostream>
#include <string>
class Residence {
// Granting global function access to private sections
friend void inspectInterior(const Residence* home);
public:
Residence() {
this->livingRoom = "Living Area";
this->masterSuite = "Master Bedroom";
}
std::string livingRoom; // Public accessible area
private:
std::string masterSuite; // Restricted private area
};
void inspectInterior(const Residence* home) {
std::cout << "Accessing public space: " << home->livingRoom << std::endl;
std::cout << "Accessing private space: " << home->masterSuite << std::endl;
}
void demonstrate() {
Residence myHome;
inspectInterior(&myHome);
}
Entire Classes as Friends
When one class requires comprehensive access to another class's internals, the entire class can be declared as a friend. This establishes a bidirectional trust relationship where all member functions of the friend class may access private and protected members of the declaring class.
#include <iostream>
#include <string>
// Forward declaration
class Residence;
class PropertyInspector {
public:
PropertyInspector();
void performInspection();
~PropertyInspector();
private:
Residence* targetProperty;
};
class Residence {
// Entire PropertyInspector class becomes a friend
friend class PropertyInspector;
public:
Residence() : commonArea("Entrance Hall"), restrictedZone("Vault") {}
std::string commonArea;
private:
std::string restrictedZone;
};
PropertyInspector::PropertyInspector() {
targetProperty = new Residence();
}
PropertyInspector::~PropertyInspector() {
delete targetProperty;
}
void PropertyInspector::performInspection() {
std::cout << "Inspecting: " << targetProperty->commonArea << std::endl;
std::cout << "Inspecting: " << targetProperty->restrictedZone << std::endl;
}
void demonstrate() {
PropertyInspector inspector;
inspector.performInspection();
}
Specific Member Functions as Friends
For finer granularity, individual member functions from another class can be designated as friends rather than the entire class. This selective approach minimizes exposure of internal implementation details while permitting specific operations.
#include <iostream>
#include <string>
class SecureFacility;
class SecurityAuditor {
public:
SecurityAuditor();
void fullAudit(); // Granted friend access
void visualCheck(); // No special access
private:
SecureFacility* facility;
};
class SecureFacility {
// Only SecurityAuditor::fullAudit receives privileged access
friend void SecurityAuditor::fullAudit();
public:
SecureFacility() : lobby("Reception"), controlRoom("Server Room") {}
std::string lobby;
private:
std::string controlRoom;
};
SecurityAuditor::SecurityAuditor() : facility(new SecureFacility()) {}
void SecurityAuditor::fullAudit() {
std::cout << "Audit - Public area: " << facility->lobby << std::endl;
std::cout << "Audit - Secured zone: " << facility->controlRoom << std::endl;
}
void SecurityAuditor::visualCheck() {
std::cout << "Visual check - Public area: " << facility->lobby << std::endl;
// Error: cannot access facility->controlRoom from here
}
void demonstrate() {
SecurityAuditor auditor;
auditor.fullAudit();
}
Key Considerations
Friend declarations are not member functions and do not modify the class's interface from the perspective of inheritance or polymorphism. They break encapsulation and should be used judiciously when the benefits of tight coupling outweigh the costs of exposing internal state. Friend relationships are not transitive; if class A is a friend of B, and B is a friend of C, A does not automatically become a friend of C.