C++ Friendship and Inheritance

C++ Friendship is the feature of declaring classes or functions with friend keyword. The classes or functions declared with friend keyword have a relationship of friendship with the class.

C++ Inheritance

Inheritance and abstraction are major features of object oriented programming OOP. In OOP there are following access specifiers that help achieve inheritance.

  • Public
  • Protected
  • Private

In inheritance classes can have public, protected or private members. The public members of a class are accessible from inside and outside of class. The protected members are only accessible for base and derived classes. Whereas the private members are only accessible from within the class.

C++ Friendship

C++ Friendship bypasses inheritance. Note that friendship is not inheritance. As friend function or friend members of a class can access the private members of a class as well. Whereas, child classes cannot inherit the private members of a class. There are two types of friendship in C++:

  • C++ Friend Functions
  • C++ Friend Classes

C++ Friend Functions

C++ Friend Functions can inherit the public, private or protected data of a class. Friend functions are not a member of class and still they have access to not only public and protected but private members of the class as well. The syntax for declaring a friend function inside the class is:

Here className is the name of class. The syntax is that the keyword friend is followed by function return type, which is followed by function name and parenthesis (). Here function name is functionName and return type is return_type.

The friend function definition can be present outside the class. For example, the code below shows the concept of friend functions. The following code has a class Location. The location class has two private variables longitude and latitude. Note that if a class member has no access specifier mentioned, then by default those members will have private access specifier.

The Location class also has a constructor and a friend function printCoordinates. The friend function is declared inside the class. But its definition is present outside the class. Since printCoordinates is a friend function so it is accessing private members (longitude, latitude) of the class from outside the class scope. If any other function than friend function accesses the private members of the class then in this case, error will arise.

The printCoordinates friend function prints the latitude and longitude values. Note that here the printCoordinates function is not a member of Location class.

#include <iostream> 
using namespace std; 
class Location {
    double longitude, latitude;
  public:
    Location() {}
    Location (double lon, double lat) : longitude(lon), latitude(lat) {}
    friend Location printCoordinates (const Location&);
};
Location printCoordinates (const Location& param)
{
  Location loc;
  loc.longitude = param.longitude;
  loc.latitude = param.latitude;
  cout << "The coordinates are " << loc.longitude;
  cout << ", " << loc.latitude << endl;
  return loc;
}
int main () {
  Location l1;
  Location coord (28.2,-92.3);
  l1 = printCoordinates (coord);
  return 0;
}

The output of the above code after compilation is:

C++ Friend Classes

Just like friend functions, a class can also have friend classes. Friend class can have access to the private, protected and public members of another class. The syntax for declaring a friend class is:

Here class B is friend of class A. When class B becomes friend of class A, all functions of class A become friend functions. That means class B can access all members (variables and functions) of class A. However, class A cannot access all members of class B. C++ friendship does not work both ways because it is granted and not taken.

There is no concept of mutual friends in C++ Friendship as it is not transitive. That means friend of friend is not a friend. Unless a class is not declared as a friend class, it cannot avail the benefits of friendship.

Accessing Friend Variables

For example the code below shows the concept of friend class. In the following code, there are two classes Alpha and Beta. Class Beta is friend of class Alpha. Class Alpha has a private member that is x having value 10. Alpha constructor defines the value of variable x to be 10. The line friend class Beta; makes class Beta class friend of class Alpha. Due to the friendship class Beta can use private members like x variable, of class Alpha. Below, class Beta accesses x through its printAlpha function that prints the value of x.

#include <iostream> 
using namespace std;
class Alpha { 
private: 
    int x; 
public: 
    Alpha() { 
        x = 10; 
        } 
    friend class Beta; 
}; 
class Beta {  
public: 
    void printAlpha(Alpha& y) 
    {
        cout << "The private member of class Alpha accessed through class Beta function is: x = " << y.x; 
    } 
}; 
int main() 
{ 
    Alpha a1; 
    Beta b1; 
    b1.printAlpha(a1); 
    return 0; 
}

The output of the above code after compilation is:

Accessing Friend Functions

In the above example friend class accesses private variable of another class. Just like variables, friend classes can also access functions of other class. Scope resolution operator (::) is used to declare and define friend function. The syntax for declaring friend function of another class is:

Here friend is the keyword, func_return_type is the return type of function. Class_name is the name of class and func_name is the name of function. Function definition is present outside the class. The scope resolution operator (::) is also used in function definition. For example, the code below shows the concept of calling friend function of another class.

#include <iostream> 
using namespace std; 
class Beta; 
class Alpha { 
public: 
    int printBeta(Beta&); 
}; 
class Beta { 
private: 
    int i; 
public: 
    Beta() { i = 20; } 
    friend int Alpha::printBeta(Beta& x);
}; 
int Alpha::printBeta(Beta& obj) 
{
    cout << "The value of private member of class Beta is: " << obj.i;
    return 0;
} 
int main() 
{ 
    Alpha a1; 
    Beta b1; 
    a1.printBeta(b1); 
    return 0; 
}

The output of the above code after compilation is: