C++. Operators overloading -> and ‘,’ (comma). Examples

Operators overloading -> and ‘,’ (comma). Examples


Contents



1. The overloading of the operator ->. General form. Operator function operator->()

In C++, the operator access to a member of an object -> can be overloaded. If the operator -> is overloaded, the call of the class element has the following general form

obj->item

here

  • obj – class object;
  • item – some class element (internal variable, method). This member must be a member of the class that is available inside the object.

When overloading, the following features should be considered:

  • the operator -> is considered unary;
  • the operator function operator->() should return a pointer to an object of the class for which it is defined;
  • operator function operator->() must be a member of the class for which it is implemented.

The general form of the class in which the operator -> is overloaded

class ClassName
{
    // ...

    // operator function
    ClassName* operator->()
    {
        // operator function body
        // ...

        return this; // return pointer to class object
    }
};

 

2. An example of operator overloading -> in a class that contains a single internal variable of type double

The class Double is declared, containing an internal variable d of type double. The class implements the overloaded operator function operator->(), which overloads the operator ->.

#include <iostream>
using namespace std;

class Double
{
public:
    double d; // internal variable

    // operator function, which overloads operator ->
    Double* operator->()
    {
        return this; // return a pointer to the class
    }
};

void main()
{
    // access operator overload by pointer ->
    Double D; // instance of class D
    double x;

    D.d = 3.85;

    // invoke the operator function operator->()
    x = D->d;

    // another access method
    x = D.d; // x = 3.85

    cout << "x = " << x;
}

The result of the program

x = 3.85

 

3. Example of operator overloading -> for a class that contains a dynamic array of class instances

The example demonstrates operator overloading -> for a class in which a dynamic array of class objects (instances) is implemented.

A Point class is set that implements a point on the plane. The Point class implements the following elements:

  • internal variables x, y – point coordinates;
  • constructors;
  • access methods GetX(), GetY(), SetXY().

Also the Polygon class, which implements an array of points is specified. The class declares:

  • internal private variable a pointer to type Point. This variable contains a pointer to a dynamic array of points of type Point;
  • internal private variable n, which determines the number of elements in the array;
  • constructor;
  • method GetN() that intended to get the value of n;
  • method Add(), which adds a new point of type Point to the array. A new point is obtained as a parameter of the method;
  • the Delete() method, which deletes a point at a given index position. The index position is the input parameter of the method;
  • method GetPoint(), which returns the value of a point of type Point at a given position index;
  • method Show(), which displays the value of the array of points in the Polygon class;
  • operator function operator->(), which overloads the operator->.

The text of the program of the Console Application type, containing implementations of the Point and Polygon classes, is the following

#include <iostream>
using namespace std;

// class that implements the point
class Point
{
private:
    double x, y; // internal variables

public:
    // class constructors
    Point()
    {
        x = y = 0;
    }

    Point(double x, double y)
    {
        this->x = x;
        this->y = y;
    }

    // access methods
    void SetXY(double x, double y)
    {
        this->x = x;
        this->y = y;
    }

    double GetX(void) { return x; }
    double GetY(void) { return y; }
};

// polygon class
class Polygon
{
private:
    Point * Pt; // array of points
    int n; // number of points

public:
    // constructor
    Polygon()
    {
        n = 0;
        Pt = NULL;
    }

    // access methods
    // get the number of points
    int Get(void) { return n; }

    // add a new point
    void Add(Point p)
    {
        Point * Pt2;

        // allocate memory for a new array of type Point + 1 element more
        Pt2 = new Point[n + 1];

        // copy Pt=>Pt2
        for (int i = 0; i < n;i++)
            Pt2[i].SetXY(Pt[i].GetX(), Pt[i].GetY());

        // add extra item
        Pt2[n].SetXY(p.GetX(), p.GetY());

        // release the memory allocated for the old array
        if (n > 0)
            delete[] Pt;

        // assign a new array of the internal variable
        Pt = Pt2;
        n++;
    }

    // delete point at position pos
    void Delete(int pos)
    {
        if (n < 0) return;
        if (pos > (n - 1)) return;
        if (pos < 0) return;

        // if one item, then delete it
        if (n == 1)
        {
            n = 0;
            delete[] Pt;
            return;
        }

        // n>1
        Point* Pt2; // new array
        double tx, ty; // additional variable

        Pt2 = new Point[n - 1]; // allocate memory for a new array - 1 element less

        // copy Pt to Pt2 bypassing pos position
        // before the position pos
        for (int i = 0; i < pos; i++)
        {
            tx = Pt[i].GetX();
            ty = Pt[i].GetY();
            Pt2[i].SetXY(tx, ty);
        }

        // after the position pos
        for (int i = pos + 1; i < n; i++)
        {
            tx = Pt[i].GetX();
            ty = Pt[i].GetY();
            Pt2[i-1].SetXY(tx, ty); // Pt2[i-1] - important
        }

        // release memory allocated for Pt before
        delete[] Pt;

        // reduce the number of items by 1
        n--;

        // set a new value Pt
        // redirect Pt to Pt2
        Pt = Pt2;
    }

    // take the point from the index position
    Point GetPoint(int index)
    {
        if ((index >= 0) && (index < n))
            return Point(Pt[index].GetX(), Pt[index].GetY());
        else
            return Point(0.0, 0.0);
    }

    // method that outputs an array
    void Show(void)
    {
        double x, y;
        int i;

        for (i = 0; i < n; i++)
        {
            x = Pt[i].GetX();
            y = Pt[i].GetY();
            cout << "x" << i + 1 << " = " << x << ",   ";
            cout << "y" << i + 1 << " = " << y;
            cout << endl;
        }
    }

    // operator function that overloads the operator ->
    Polygon* operator->()
    {
        return this;
    }
};

void main()
{
    // access operator overload by pointer ->
    Polygon Pol; // the instance of class Polygon
    double x, y;
    int i;
    Point Pt;

    // create an arbitrary array of 5 points
    for (i = 0; i < 5; i++)
    {
        x = (double)(i * 2);
        y = (double)(i + 3);
        Pt.SetXY(x, y); // form a point

        // invoke the operator function operator->
        Pol->Add(Pt); // add a point
    }

    cout << "Array of points: \n";

    // output an array using a call to the operator function operator->()
    Pol->Show();

    // delete point at position 2
    Pol->Delete(2);

    cout << "Modified array: \n";
    cout << "n = " << Pol->Get() << endl;

    //
    Pol->Show();
}

The result of the program

Array of points:
x1 = 0,   y1 = 3
x2 = 2,  y2 = 4
x3 = 4,   y3 = 5
x4 = 6,   y4 = 6
x5 = 8,   y5 = 7
Modified array:
n =4
x1 = 0,   y1 = 3
x2 = 2,   y2 = 4
x3 = 6,   y3 = 6
x4 = 8,   y4 = 7

 

4. Features operator overload ‘ , ‘ (comma). Operator function operator,()

In C++, the operator ‘ , ‘ may be overloaded. When the operator ‘ , ‘ is overloaded in the class, the operator function operator,() must be declared. Any code can be placed in the body of an operator function. If desired, the ‘ , ‘ operator can perform any non-standard operations on objects of a class.

In the standard case, the operator ‘ , ‘ is used in the assignment operation as follows

obj1 = (obj2, obj3, ..., objN);

where obj1, …, objN – instances of some class.

In the case of the standard use of the operator ‘ , ‘ the following features should be taken into account:

  • the operator ‘ , ‘ is considered binary. Therefore, the operator function operator,() takes one parameter;
  • when using the overloaded operator ‘ , ‘ in the assignment operation, the last argument is taken into account (this argument is the result of the operation). All other arguments are ignored.

In general, when the operator is overloaded, the class has the following form

class ClassName
{
    // ...

    // operator function that overloads the operator ','
    ClassName operator,(ClassName obj)
    {
        // ...
    }
};

where

  • ClassName – the name of the class in which the operator ‘ , ‘ is overloaded;
  • obj – the name of the class instance that is passed as a parameter to the function operator,().

 

5. Example of operator overloading ‘ , ‘

In the example, the operator ‘ , ‘ is overloaded in the class Coords3D, which implements the coordinates in space. The class declares:

  • three internal hidden variables with the names x, y, z;
  • two class constructors;
  • access method Get(), designed to get the values of x, y, z;
  • the operator function operator,(), which overloads the operator ‘ , ‘.

The program code for an application like Console Application is as follows

#include <iostream>
using namespace std;

// the class that defines the coordinates of a point in space
class Coords3D
{
private:
    double x, y, z;

public:
    Coords3D()
    {
        x = y = z = 0;
    }

    Coords3D(double x, double y, double z)
    {
        this->x = x;
        this->y = y;
        this->z = z;
    }

    // method of reading x, y, z
    void Get(double& x, double& y, double& z)
    {
        x = this->x;
        y = this->y;
        z = this->z;
    }

    // overloaded operator ,
    Coords3D operator,(Coords3D obj)
    {
        Coords3D tmp;
        tmp.x = obj.x;
        tmp.y = obj.y;
        tmp.z = obj.z;
        return tmp;
    }
};

void main()
{
    double x, y, z;
    Coords3D c1(1, 3, 5); // instances of class Coords3D
    Coords3D c2(2, 4, 6);
    Coords3D c3;

    // invoke the operator function c3.operator,(c2)
    c3 = (c1, c2); // into c3 is saved c2

    // checking
    c3.Get(x, y, z); // x = 2, y = 4, z = 6

    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;

    //------------------------
    //create another instance
    Coords3D c4(10, 15, 20);

    c3 = (c2, c1, c4); // c3 <= c4

    // checking
    c3.Get(x, y, z); // x = 10, y = 15, z = 20

    cout << endl;
    cout << "x = " << x << endl;
    cout << "y = " << y << endl;
    cout << "z = " << z << endl;
}

In the above code in line

c3 = (c1, c2);

operator function c3.operator, (c2) is called. This means that the last copy c2 is taken into consideration. An instance named c1 is ignored. This also applies to the line.

c3 = (c2, c1, c4);

where object c3 is assigned the value of internal variables of object c4.

Conclusion: in the case of standard use, when the operator is overloaded, the last right argument is taken into account. All other arguments are ignored.

The result of the program

x = 2
y = 4
z = 6

x = 10
y = 15
z = 20

 


Related topics