Lesson 5 | Friend Functions in C++ |
Objective | Compare the use of friend functions and member functions in a Matrix class |
In C++, the friend
keyword allows a non-member function—or even another class—to access the private and protected members of a class.
While this seems to “break” encapsulation, there are scenarios where such access is justified and results in cleaner, more efficient code.
Still, use of friends should be carefully considered: they are a precise but potentially dangerous tool.
+
or ==
often requires access to the internals of two different objects.
class Matrix; // forward declaration
class Vector {
public:
friend Vector multiply(const Vector& v, const Matrix& m);
explicit Vector(int size);
private:
std::vector<int> data;
};
class Matrix {
public:
friend Vector multiply(const Vector& v, const Matrix& m);
Matrix(int rows, int cols);
private:
std::vector<std::vector<int>> data;
};
Vector multiply(const Vector& v, const Matrix& m) {
assert(v.data.size() == m.data.size());
Vector result(m.data[0].size());
for (size_t i = 0; i < m.data[0].size(); ++i) {
int sum = 0;
for (size_t j = 0; j < v.data.size(); ++j) {
sum += v.data[j] * m.data[j][i];
}
result.data[i] = sum;
}
return result;
}
Here the non-member multiply()
function is declared as a friend of both classes, enabling efficient implementation without exposing private members globally.
Unlike member functions, friend functions accept all arguments explicitly. This enables user-defined conversions when calling the function:
class PandaBear {
public:
PandaBear(int age);
friend int getAge(const PandaBear&);
private:
int age;
};
int getAge(const PandaBear& p) { return p.age; }
int main() {
// implicit conversion: int → PandaBear
int age = getAge(5);
}
In this example, the call getAge(5)
works because the int
is converted into a PandaBear
using the constructor, which would not occur with a member function.
You can declare entire classes or specific functions as friends:
class Account {
friend class AccountManager;
friend void applyFee(Account& a, double fee);
public:
explicit Account(double balance);
void deposit(double amt);
double getBalance() const;
private:
double balance;
};
operator+ (a, b)
).
Try writing two add()
functions for a Matrix
class:
friend
function.Compare their design trade-offs and explain when one approach is preferable. Because friends are named, and because friends are allowed direct access to internal data fields, friendship is a more precise and efficient mechanism than, for example, the creation of accessor functions[1] .
add()
functions to the matrix class
.
friend
function and