The Concept of Friendship:


In Object-Oriented Programs, encapsulation and data hiding are fundamental features. Encapsulationinvolves bundling data and functions together in objects, while data hidingentails creating private class members inaccessible to functions outside the class. Previously, we explored data hiding, ensuring private member data in a class is only accessible to functions within the class, promoting correct and appropriate use.

However, there are situations where it's practical to grant access to private data members to outside, non-member functions. For instance, a class storing data might need a function or another class to display that data. Although separating storage and display enhances maintainability, the display code relies heavily on the storage class details, minimizing the benefits of hiding these details.

In such cases, we have two options:

1:

Utilize the storage class's publicly exposed functions for the display code. However, this approach has drawbacks. It requires defining public member functions, potentially cluttering the storage class interface. Additionally, the storage class might have to expose functions to the display code, which aren't meant for general access.


2:

Alternatively, we can employ friend classes and friend functions to grant the display code access to the storage class's private details. This allows the display code to directly interact with all private members and functions of the storage class while preventing access from others. This tutorial delves deeper into implementing this approach.

A friend function is a function capable of accessing non-public members (private and protected)of a class, even though it's not a member of the class itself. It's a regular function with special access privileges.

In our daily interactions, we often share private information with friends that we wouldn't disclose to the public. Similarly, in C++, a function or class designated as a friend can access the private information within a class.

To enable an external function to access the private and protected members of a class, we declare the function prototype preceded by the keyword friendwithin the class declaration. The basic syntax for declaring a friend function is:

friend Return_type Function_name(class_name);

In the above syntax, friendis the keyword used to declare the friend function, and Return_typecan be any data type.

Consider the following example:

class SUM {
    friend void Access(SUM); // Friend function prototype declared.

    private:
        int a;

    public:
        SUM() { a = 10; } // Constructor.
};

In this example, the function Access()is declared as a friend of the class SUM. Although Access()is not a member of SUM, it can access the private members of SUMbecause of the friendship declaration.

FRIEND FUNCTION - C++ Copy to Clipboard  
#include<iostream>
using namespace std;

class SUM {
    friend void Access(SUM); // Friend function prototype declared.

    private:
        int a;

    public:
        SUM() { a = 10; } // Constructor.
};

void Access(SUM obj) { // Friend function definition.
    obj.a = obj.a + 30; // Access and modify private data using object "obj".
    cout << "The Value of A is " << obj.a;
}

int main() {
    SUM Obj; // Object creation.
    Access(Obj); // Calling the friend function.

    return 0;
}

In this simple example above, we declare a friend function prototype within the class body and define the class outside. The function Access()is not a member function, hence requiring an object of class SUMto be passed as a parameter.

A function can be a friend of more than one class simultaneously using the same syntax.

friend Return_type Function_name(class1, class2, class3);

In the above syntax, friendis the keyword used to declare the friend function, and Return_typecan be any data type.

Consider the following example:

FRIEND FUNCTION - C++ Copy to Clipboard  
#include<iostream>
using namespace std;

class B; // Class B Prototype.

class A {
    friend void Add(A, B); // Friend Function Prototype.

private:
    int a;

public:
    A() { a = 0; } // Constructor.
};

class B {
    friend void Add(A, B); // Friend function prototype.

private:
    int b;

public:
    B() { b = 0; } // Constructor.   
};

void Add(A ob1, B ob2) {
    ob1.a = 10; // Assign Value to Class A Private Member.
    ob2.b = 5;  // Assign Value to Class B Private Member.

    cout << "The Value Of A is " << ob1.a << endl;
    cout << "The Value Of B is " << ob2.b << endl;

    cout << "The Sum is: " << ob1.a + ob2.b << endl;
}

int main() {
    A OBJ1; // Class A object.
    B OBj2; // Class B object.
    Add(OBJ1, OBj2); // Friend function Calling:

    return 0;
}

Similar to friend functions, it's possible to make an entire class a friend of another class. When a class becomes a friend, all its member functions also become friends of the other class. This requires declaring or defining the friend class beforehand.

The basic syntax to make a class a friend is:

friend class class-name;

In this syntax, friendand classare keywords, and class_namecan be any existing class. If the class doesn't exist, its prototype must be used at the top of the friend class.

Consider the following example:

FRIEND CLASS - C++ Copy to Clipboard  
#include<iostream>
using namespace std;

class A; // Class A prototype.
class B {
    friend class A; // Friend class declaration.
    private:
        int Y; // Private member to access.
    public:
        B() { Y = 0; } // Constructor.
};

class A {
    private:
        int X; // Private member.
    public:
        A() { X = 10; } // Constructor.

        // Function with Class B and its object as parameters.
        void add(B obj) { 
            obj.Y = 25; // Accessing Class B's private member.
            cout << obj.Y << " + " << X << " = " << obj.Y + X << endl;
        }
};

int main() {
    A Obj1; // Class A object.
    B Obj2; // Class B object.

    /* Calling function using Class A object, which needs 
     Class B object as a parameter */
    Obj1.add(Obj2);

    return 0;
}

In this example, we start with the prototype of Class B to ensure proper compilation order. We then declare a simple example of class friendship, demonstrating accessing members of one class from another for a specific purpose.