C++. “Friends” of the class. “Friendly” classes and functions. The keyword friend. Examples

“Friends” of the class. “Friendly” classes and functions. The keyword friend. Examples


Contents


Search other websites:

1. For what are used so called “friends” of the class?

There are times when for a given class you need to declare another class or function that must have unlimited access to the internal variables and methods of the class. This need arises from the essence of the problem being solved.

If class A is declared “friendly” to class B, then objects of class A have access to all data members and methods of class B. If a function is declared to be “friendly” to some class, then this function also has unlimited access to data members and methods of this class. Thus, the “friendly” class or function complement the functional of the class in which they are declared as “friendly”.

2. What is the general form of declaring a “friendly” class? The keyword ‘friend’

To declare a “friendly” class to this class, the friend keyword is used. The general form of declaring a “friendly” class to this one looks like this:

class CClass
{
    // ...

    friend class CFriendClass;

    // ...
};

class CFriendClass
{
    // ...
};

where

  • CClass – class in which the “friendly” class CFriendClass is declared. All variables (even private) and methods of this class are available for objects of class CFriendClass;
  • CFriendClass – class, which is “friendly” to the class CClass. The declaration of the “friendly” class CFriendClass to the class CClass can be anywhere in the body of the class – within the declaration of the class (between curly braces { }).

3. What is the general form of declaring a “friendly” function to a certain class?

The declaration of a “friendly” function to a class begins with the keyword friend. The general form of declaring a “friendly” function to a class is:

friend type FunName(parameters);

where

  • FunName – the name of the ‘friendly’ function;
  • type – type, which is returned by the function FunName();
  • parameters – a parameters of friendly function. To get the object of the desired class in the function FunName(), it is advisable to pass into this function a reference (or pointer) to the object of this class.

If you want to declare a “friendly” function in a certain class, then the general form of this declaration is as follows:

class CClass
{
    // ...

    friend type FunName(parameters);

    // ...
};

where

  • FunName – the name of the ‘friendly’ function;
  • type – type, which is returned by the function FunName();
  • parameters – a parameters of friendly function.

4. Where in the class declaration, you can declare a “friendly” class or function?

You can declare a “friendly” class or function to a given class anywhere in the class section within its declaration (between curly braces { } ).






5. How many friendly functions and friendly classes can be declared in the class body?

As many as you like.

6. How to get the object of the desired class in a “friendly” function to have access to all its members? Example

To get the object of the desired class in a function, it is advisable to pass into this function a reference (or pointer) to an object of this class.

For example. Suppose we have a class named CMyClass. It is needed to declare a “friendly” function to this class, which is called FriendFun(). The function returns an int parameter. The declaration of the CMyClass class and the “friendly” function in the class has the following form:

// declaration of class CMyClass, in which there is a "friendly" function FriendFun()
class CMyClass
{
    // body of class
    // ...

    friend int FriendFun(CMyClass &);

    // ...
};

Implementation of friendly function FriendFun():

int FriendFun(CMyClass & mc)
{
    // using an object of class mc to access members of the CMyClass class
    // ...
};

7. An example of declaring a class that is “friendly” to another class

Let the class Number be specified, which contains an integer value. A RangeNum class is also defined that contains the Number value but within the specified range.

In order for RangeNum to be able to access the private variable num of the Number class, the RangeNum class is declared “friendly” to the Number class.

Listing of the Number and RangeNum classes looks like this:

// class that implements an integer
class Number
{
    // declare a "friendly" RangeNum class to the Number class
    friend class RangeNum;
    int num;

    public:
    // constructors
    Number() { num = 0; }
    Number(int num) { this->num = num; }
};

    // declaration of the RangeNum class containing the Number in the specified limits
    class RangeNum
    {
        Number num; // the object of class Number - integer number
        int min; // the lower limit of the number of num
        int max; // the upper limit of num

        public:
        // constructor
        RangeNum()
        {
            // access to the private member of the Number class, since the RangeNum is "friendly" to the Number class
            num.num = 0;

            // setting of range 0..99 by default
            min = 0;
            max = 99;
    }

    // access methods
    int GetNum(void)
    {
        return num.num; // access to a private member from the "friendly" Range class
    }

    void SetNum(int nnum)
    {
        num.num = nnum; // access to a private member from the "friendly" Range class
        if (num.num>max) num.num = max-1;
        if (num.num<min) num.num = min;
    }

    // setting the range for num within the specified bounds
    void SetRange(int min, int max)
    {
        this->min = min;
        this->max = max;
        if (num.num>max) num.num = max-1; // again access by using the "friendly" class
        if (num.num<min) num.num = min;
    }
};

Using classes in another program code

int _tmain(int argc, _TCHAR* argv[])
{
    // the object of class RangeNum
    RangeNum r;
    int d;

    d = r.GetNum(); // d = 0

    r.SetRange(100, 200);
    r.SetNum(101);
    d = r.GetNum(); // d = 101

    r.SetRange(10, 20); // value num is corrected
    d = r.GetNum(); // d = 19

    r.SetNum(-10);
    d = r.GetNum(); // d = 10

    return 0;
}

If in the class Number in the declaration of the “friendly” class RangeNum

friend class RangeNum;

remove the keyword friend, then in the constructor and all methods of the class when accessing num.num the compiler will generate an error:

Number::num: cannot access private member declared in class 'Number'

8. An example of declaring a function that is “friendly” to another class

In the example, the Radius class is declared, containing the radius value of some geometric figure. In the class are declared:

  • one private variable ‘radius’;
  • methods Get(), Set() to access the variable radius;
  • two external “friendly” functions GetLength() and GetArea();
  • one friendly class Volume. The class Volume declares the public method GetVolume(), which returns the volume of a sphere of a given radius.

The listing of application of “Win32 Console Application” type is as follows:

#include "stdafx.h"
#include <iostream>
using namespace std;

// class that realizes the radius of a geometric figure
class Radius
{
    private:
    double radius; // private variable radius

    // declaration of "friendly" functions - in any section of the Radius class
    friend double GetLength(Radius &);
    friend double GetArea(Radius &);

    // declaring a friendly class
    friend class Volume;

    public:
    // methods of access to the radius variable
    double Get(void) { return radius; }
    void Set(double nradius) { radius = nradius; }
};

// "friendly" functions to the Radius class
// circumference
double GetLength(Radius & r)
{
    // access to the private member of the radius class from the "friendly" function GetLength()
    return (double)(2 * r.radius * 3.1415);
}

// area of a circle
double GetArea(Radius & r)
{
    // access to the private member of the radius class from the "friendly" function GetArea()
    return (double)(r.radius * r.radius * 3.1415);
}

// declaring a friendly class
class Volume
{
    public:
    // the class contains only one function Volume
    double GetVolume(Radius * r) // function receives a pointer to Radius
    {
        // access to the private member of the Radius class from the "friendly" class Volume
        return (double)(4.0 / 3.0 * 3.1415 * r->radius * r->radius * r->radius);
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    // the object of class Radius
    Radius r;
    Volume v;
    double len, area, vol;

    r.Set(3);

    // calling the external "friendly" function GetLength()
    len = GetLength(r); // transfer of a Radius class object by reference

    // calling the external "friendly" function GetArea()
    area = ::GetArea(r); // passing by reference

    // calling a function of "friendly" class
    vol = v.GetVolume(&r); // passing by pointer

    cout << "Length = " << len << endl; // Length = 9.4245
    cout << "Area = " << area << endl; // Area = 28.2735
    cout << "Volume = " << vol << endl; // Volume = 113.094

    return 0;
}

As you can see from the above code, “friendly” functions receive an input parameter as a reference or pointer to a class object, to which data members and methods they have unlimited access.

9. Features of using “friendly” functions

We can say the following about “friendly” functions:

  • “friendly” function does not receive the this pointer of the class in which it is implemented
  • class objects are passed to the “friendly” function explicitly via parameters
  • “friendly” functions are not called through the class object of which they are friends
  • “friendly” functions are not affected by access specifiers private, protected, public
  • “friendly” function is not a component of the class to which it is “friendly”
  • “friend” function can be “friend” of several classes


Related topics