Friend Functions and Their Use in Operator Overloading in C++


Friend functions in C++ are functions that are not members of a class but have access to the private and protected members of the class. They are declared using the keyword friend. Friend functions are especially useful when overloading certain operators that require access to private data from multiple objects.

What is a Friend Function?

A friend function is a non-member function that is granted special access privileges to private and protected members of a class. It is declared in the class definition using the friend keyword.

Friend functions are commonly used for:

  • Overloading binary operators that require access to private members of multiple objects.
  • Implementing functions that need to operate closely with a class while not being part of its interface.

Example: Overloading Binary + Operator

Below is an example where a friend function is used to overload the binary + operator for adding two objects of a user-defined class:

    #include <iostream>

    class Point {
    private:
        int x, y;

    public:
        Point(int x = 0, int y = 0) : x(x), y(y) {}

        // Friend function for operator+
        friend Point operator+(const Point& p1, const Point& p2);

        void display() const {
            std::cout << "(" << x << ", " << y << ")";
        }
    };

    // Definition of friend function
    Point operator+(const Point& p1, const Point& p2) {
        return Point(p1.x + p2.x, p1.y + p2.y);
    }

    int main() {
        Point p1(1, 2), p2(3, 4);
        Point p3 = p1 + p2;

        std::cout << "Point 1: ";
        p1.display();
        std::cout << "\nPoint 2: ";
        p2.display();
        std::cout << "\nSum: ";
        p3.display();
        std::cout << std::endl;

        return 0;
    }
        

Output:

    Point 1: (1, 2)
    Point 2: (3, 4)
    Sum: (4, 6)
        

In this example, the friend function operator+ has access to the private members x and y of the Point objects.

Example: Overloading Comparison Operators

Friend functions can also be used to overload comparison operators, such as ==:

    #include <iostream>

    class Rectangle {
    private:
        int width, height;

    public:
        Rectangle(int width, int height) : width(width), height(height) {}

        // Friend function for operator==
        friend bool operator==(const Rectangle& r1, const Rectangle& r2);
    };

    // Definition of friend function
    bool operator==(const Rectangle& r1, const Rectangle& r2) {
        return r1.width == r2.width && r1.height == r2.height;
    }

    int main() {
        Rectangle r1(4, 5), r2(4, 5), r3(6, 7);

        std::cout << "r1 == r2: " << (r1 == r2 ? "True" : "False") << std::endl;
        std::cout << "r1 == r3: " << (r1 == r3 ? "True" : "False") << std::endl;

        return 0;
    }
        

Output:

    r1 == r2: True
    r1 == r3: False
        

Here, the friend function operator== accesses private members width and height of both Rectangle objects to compare them.

Example: Overloading Stream Operators

Stream operators << and >> are typically implemented as friend functions since they need access to private members of the class:

    #include <iostream>

    class Complex {
    private:
        double real, imag;

    public:
        Complex(double real = 0, double imag = 0) : real(real), imag(imag) {}

        // Friend function for operator<<
        friend std::ostream& operator<<(std::ostream& out, const Complex& c);

        // Friend function for operator>>
        friend std::istream& operator>>(std::istream& in, Complex& c);
    };

    // Definition of operator<<
    std::ostream& operator<<(std::ostream& out, const Complex& c) {
        out << c.real << " + " << c.imag << "i";
        return out;
    }

    // Definition of operator>>
    std::istream& operator>>(std::istream& in, Complex& c) {
        std::cout << "Enter real part: ";
        in >> c.real;
        std::cout << "Enter imaginary part: ";
        in >> c.imag;
        return in;
    }

    int main() {
        Complex c1, c2(3, 4);
        std::cout << "Enter a complex number:\n";
        std::cin >> c1;

        std::cout << "You entered: " << c1 << std::endl;
        std::cout << "Another complex number: " << c2 << std::endl;

        return 0;
    }
        

Output (Example Interaction):

    Enter a complex number:
    Enter real part: 5
    Enter imaginary part: 6
    You entered: 5 + 6i
    Another complex number: 3 + 4i
        

The friend functions operator<< and operator>> access private members real and imag of the Complex class to perform input and output operations.

Conclusion

Friend functions are powerful tools in C++ that allow non-member functions to access private and protected data of a class. They are particularly useful for operator overloading, enabling seamless and intuitive operations on user-defined types. While friend functions provide flexibility, they should be used judiciously to maintain encapsulation and prevent unnecessary coupling between classes.





Advertisement