Operator Overloading  «Prev  Next»
Lesson 5 Friend Functions in C++
Objective Compare the use of friend functions and member functions in a Matrix class

Understanding Friend Functions in C++

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.

When Friend Functions Are Useful


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.

Argument Passing and Conversions

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.

Friend Classes and Functions

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;
};

Guidelines for Using Friends

  1. Prefer member functions unless non-member access provides a clear advantage.
  2. Limit friendship to specific functions instead of entire classes whenever possible.
  3. Do not overuse friend functions—they can make code harder to maintain if encapsulation is compromised.
  4. For operator overloading, friends are acceptable when symmetry is required (e.g., operator+ (a, b)).

Friend Function – Exercise

Try writing two add() functions for a Matrix class:

  1. One as a friend function.
  2. One as a member 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] .


Friend Function - Exercise

Click the Exercise link below to write two add() functions to the matrix class.
  1. one a friend function and
  2. the other a member function
and explain the advantages of defining one over the other.
Friend Function - Exercise

[1]accessor functions: Member functions that are public are called accessor functions when they do not change the object's data.

SEMrush Software