A friend function is a function that is given special access to the private and protected members of a class. Although it is not a member of the class, it can access the class’s private data as if it were a member. The friend
keyword is used to declare a friend function within the class definition.
Friend functions provide a way to give non-member functions access to class data, which can be useful for certain operations where access to private members is required, but membership in the class is not suitable.
Friend functions can be beneficial in scenarios where:
To declare a friend function, use the friend
keyword inside the class definition, followed by the function prototype. The function is defined outside the class.
class MyClass {
private:
int data;
public:
MyClass(int value) : data(value) {}
// Friend function declaration
friend void display(const MyClass& obj);
};
// Friend function definition
void display(const MyClass& obj) {
std::cout << "Data: " << obj.data << std::endl;
}
In this example, display
is declared as a friend function of the MyClass
class, allowing it to access the private member data
.
Here’s an example demonstrating the use of friend functions:
#include <iostream>
using namespace std;
class Box {
private:
double width;
public:
// Constructor
Box(double w) : width(w) {}
// Friend function to access private data
friend void printWidth(const Box& b);
};
// Definition of friend function
void printWidth(const Box& b) {
// Accessing private member of Box
cout << "Width of the box: " << b.width << endl;
}
int main() {
Box box(10.5);
printWidth(box); // Call the friend function
return 0;
}
In this example:
printWidth
function is declared as a friend inside the Box
class, allowing it to access the private member width
.Friend functions are often used for operator overloading when the left-hand operand is not an object of the class.
Example of overloading the +
operator using a friend function:
#include <iostream>
using namespace std;
class Complex {
private:
float real;
float imag;
public:
Complex(float r = 0, float i = 0) : real(r), imag(i) {}
// Friend function to overload the + operator
friend Complex operator+(const Complex& c1, const Complex& c2);
void display() const {
cout << real << " + " << imag << "i" << endl;
}
};
// Definition of friend function to overload +
Complex operator+(const Complex& c1, const Complex& c2) {
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
int main() {
Complex c1(2.5, 3.5), c2(1.5, 2.5);
Complex c3 = c1 + c2; // Uses the overloaded + operator
c3.display();
return 0;
}
In this example, the operator+
function is a friend of the Complex
class, enabling it to access the private members real
and imag
.
Besides friend functions, C++ also supports friend classes. A friend class has access to the private and protected members of another class.
class B; // Forward declaration
class A {
private:
int dataA;
public:
A(int value) : dataA(value) {}
// Making class B a friend
friend class B;
};
class B {
public:
void display(const A& a) {
// Accessing private member of class A
std::cout << "Data in class A: " << a.dataA << std::endl;
}
};
int main() {
A objA(10);
B objB;
objB.display(objA); // Accessing private data of class A
return 0;
}
Here, B
is declared as a friend class of A
, allowing B
to access A
‘s private member dataA
.
B
is a derived class of class A
, and a function is a friend of A
, it will not automatically become a friend of B
.A
declares class B
as a friend, it does not mean that class B
automatically declares class A
as a friend. Friendship is a one-way relationship.A
is a friend of class B
, and class B
is a friend of class C
, it does not mean that class A
is a friend of class C
.Friend functions are appropriate when:
Friend functions in C++ provide a mechanism to grant non-member functions special access to a class’s private and protected members. While powerful, they should be used judiciously to avoid breaking encapsulation and introducing tight coupling. When used appropriately, friend functions can enhance flexibility and enable more natural operator overloading and class interfacing.