PDFVersion
No ads? No problem! Download the PDF book of this tutorial for just $24.99. Your support will help us reach more readers.
Thank You!
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:
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.
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.
The non-public members of a class encompass both private and protected data fields and functions. We've previously addressed private and protected members in ourC++ Classes and Objectstutorials.
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 friend
within the class declaration. The basic syntax for declaring a friend function is:
friend Return_type Function_name(class_name);
In the above syntax, friend
is the keyword used to declare the friend function, and Return_type
can 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 SUM
because of the friendship declaration.
#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 SUM
to 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, friend
is the keyword used to declare the friend function, and Return_type
can be any data type.
Consider the following example:
#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;
}
Declaring the class prototype at the top is crucial. Without it, using the class name in a friend function parameter would trigger a compiler error, indicating that the class name is not declared. Hence, ensuring the class prototype is declared beforehand is vital to avoid such errors.
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, friend
and class
are keywords, and class_name
can 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:
#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.
Extensive use of friend techniques can undermine data encapsulationand data hidingprinciples, potentially leading to inconsistencies when modifying or extending a class. Special care should be taken when employing friend techniques.
Sardar Omar
I did my hardest to present you with all of the information you need on this subject in a simple and understandable manner. However, if you have any difficulties understanding this concept or have any questions, please do not hesitate to ask. I'll try my best to meet your requirements.