“Friendly” operator functions: differences, implementation

“Friendly” operator functions: differences, implementation. Overload of operators +, , *, / with the help of “friendly” operator functions

Before studying this topic, it is recommended to familiarize yourself with the following topic:


Contents



1. Differences in parameters between the operator function implemented inside the class and the “friendly” operator function

There are two ways to overload any operator:

  • using an operator function that is implemented inside the class;
  • using an operator function that is implemented as a friend to the class.

Between the ways of implementing operator functions, there is a difference in the number of parameters that an operator function receives:

  • for unary operators, the operator function within the class does not receive parameters. And the class-friendly operator function receives one parameter;
  • for binary operators, an operator function within a class receives one parameter. But “friendly” function receives two parameters. In this case, the first parameter of the “friendly” function is the left operand, and the second parameter is the right operand.

These differences are due to the fact that the “friendly” operator function does not receive an implicit pointer this. Therefore, it is necessary to explicitly set parameters in it.

 

2. The general form of an operator function that is implemented outside the class (the “friendly” function to the class)

The operator function can be implemented outside the class. If an operator function overloads a unary operator, then it contains one parameter. If the operator function overloads the binary operator, then it receives two parameters.
The general form of an operator function that is class-friendly is as follows

return_type operator#(arguments_list)
{
    // operations
    // ...
}

here

  • return_type – the type of value that the operator function returns;
  • operator# – a keyword that defines an operator function in a class. The # symbol identifies the C operator that is overloaded. For example, if operator + is overloaded, then you need to specify operator+;
  • argument_list – list of parameters that the operator function receives. If the binary operator is overloaded in the “friendly” function, the argument_list contains two arguments. If the unary operator is overloaded, argument_list contains one argument.

In a class, this function must be declared “friendly” with the friend keyword.

 

3. An example of overloading a binary operator ‘-‘ in the class for which the “friendly” operator function is implemented

In this example, you can develop your own operator functions that are “friendly” to a given class.
The Complex class, which implements a complex number, is given. The class declares internal variables, constructors, access methods, and the friend function operator-().

The “friendly” operator-() function, implemented outside the class, subtracts complex numbers.

// class Complex
class Complex
{
private:
    float real; // real part
    float imag; // imaginary part

public:
    // constructors
    Complex(void)
    {
        real = imag = 0;
    }

    Complex(float _real, float _imag)
    {
        real = _real;
        imag = _imag;
    }

    // access methods
    float GetR(void) { return real; }
    float GetI(void) { return imag; }

    void SetRI(float _real, float _imag)
    {
        real = _real;
        imag = _imag;
    }

    // declaration of a friendly operator function to the class
    friend Complex operator-(Complex c1, Complex c2);
};

// "friendly" to the class Complex operator function,
// is implemented outside the class,
// it performs the substraction of complex numbers
Complex operator-(Complex c1, Complex c2)
{
    Complex c; // create an object of class Complex

    // subtraction of complex numbers
    c.real = c1.real - c2.real;
    c.imag = c1.imag - c2.imag;

    return c;
}

Using the Complex class in another method

// use of "friendly" operator function
Complex c1(5,6);
Complex c2(3,-2);
Complex c3; // result
float a, b;

// checking
a = c1.GetR(); // a = 5
b = c1.GetI(); // b = 6

// invoke the class-friendly operator function
c3 = c1 - c2;

// result
a = c3.GetR(); // a = 5-3 = 2
b = c3.GetI(); // b = 6-(-2) = 8

As you can see from the example above, the friendly function operator-() receives two parameters. As you can see from the example above, the friendly function operator-() receives two parameters. The first parameter corresponds to the left operand in the binary subtraction operator ‘-‘. The second parameter corresponds to the right operand.

 

4. An example of overloading the ‘/’ operator that handles a class containing an array of real numbers. The operator function is implemented as a “friendly” function
// class - array of type float
class ArrayFloat
{
private:
    int size;
    float * A; // dynamic size of array

public:
    // class constructors
    // constructor without parameters
    ArrayFloat()
    {
        size = 0;
        A = NULL;
    }

    // constructor with two parameters
    ArrayFloat(int nsize, float * nA)
    {
        size = nsize;
        A = new float[size];

        for (int i=0; i<nsize; i++)
            A[i] = nA[i];
    }

    // access methods
    int GetSize(void) { return size; }
    void SetSize(int nsize)
    {
        if (size>0)
            delete A;

        size = nsize;
        A = new float[size]; // allocate a new section of memory

        // fill the array with zeros
        for (int i=0; i<size; i++)
            A[i] = 0.0f;
    }

    float GetAi(int index)
    {
        if ((index>=0) && (index<size))
            return A[index];
        else
            return 0;
    }

    void SetAi(int index, float value)
    {
        if ((index>=0) && (index<size))
            A[index] = value;
    }

    // "friendly" operator function '/',
    // declaration only, implementation outside the class
    friend ArrayFloat operator/(ArrayFloat A1, ArrayFloat A2);
};

// friendly to the class ArrayFloat operator function operator/()
// the function receives two parameters A1, A2
ArrayFloat operator/(ArrayFloat A1, ArrayFloat A2)
{
    // create an object of class ArrayFloat
    ArrayFloat A; // constructor without parameters is called
    int n;

    // get the minimum value from the size of two arrays A1, A2
    n = A1.size;
    if (n>A2.size) n = A2.size;

    // set new size of array A, memory is reallocated
    A.SetSize(n);

    // element by element division
    for (int i=0; i<n; i++)
        A.A[i] = A1.A[i] / A2.A[i];

    return A; // return a new object
}

Using the ArrayFloat class and operator-() operator function in another method

// use of friendly operator function
float F1[] = { 5.0, 2.0, 2.5, -1.0 }; // additional arrays
float F2[] = { 2.5, 1.0, -0.5 };
ArrayFloat AF1(4, F1); // objects of class ArrayFloat
ArrayFloat AF2(3, F2);
ArrayFloat AF3; // the resulting object
float x, y;

// checking 1
x = AF1.GetAi(2); // x = 2.5
y = AF2.GetAi(1); // y = 1.0

// call the friendly operator function operator/()
AF3 = AF1 / AF2; // overloaded operator /
x = AF3.GetAi(0); // x = 5.0/2.5 = 2.0
y = AF3.GetAi(2); // y = 2.5/(-0.5) = -5.0

AF3 = AF2 / AF1;
x = AF3.GetAi(0); // x = 2.5/5.0 = 0.5
y = AF3.GetAi(2); // y = -0.5/2.5 = -0.2

 


Related topics