С++. Overloading increment and decrement operators ++, –. Examples

Overloading increment and decrement operators ++, . Examples


Contents



1. Features of overloading increment and decrement operators ++,

Incremental and decrement operators in C++ can be overloaded. The feature of these operators overloading is that it is necessary to overload both the prefix and postfix forms of these operators.

As you know, in C ++, the operations ++ and have prefix and postfix forms, as shown in the example:

++x; // the prefix form of the increment operator
x++; // the postfix form of increment operator
--x; // the prefix form of the decrement operator
x--; // the postfix form of increment operator

 

2. How in the increment ++ and decrement operators it is possible to distinguish the implementations of operator functions in the class for prefix and postfix forms?

According to C ++ syntax, the decrement and increment operators require one operand. The question arises: how to implement the prefix and postfix overloaded operator function so that they differ (no matches)?

In order to distinguish the prefix and postfix forms of the implementation of the operator function ++ or when implementing in a class, the following rules must be followed:

  • if the prefix form of the operator ++ is overloaded, then in the class you need to implement the operator function operator++() without parameters;
  • if the prefix form of the operator is overloaded, then in the class you need to implement the operator–() operator function without parameters;
  • if the postfix form of the operator ++ is overloaded, then in the class it is necessary to implement the operator++(int d) operator function with one integer parameter. In this case, the parameter d is not used in the function. It is indicated only in order to indicate that this is exactly the postfix implementation of the ++ operator. The name d can be replaced by another name;
  • if the postfix form of the operator is overloaded, then in the class you need to implement the operator function operator–(int d) with one parameter. The d parameter is necessary to indicate that it is the postfix implementation of the operator that is overloaded.

For example.

class SomeClass
{
    // ...

    // operator function that overloads the prefix operator ++ (++X)
    type operator++()
    {
        // the body of the operator function
        // ...
    }

    // operator function that overloads the postfix operator ++ (++X)
    type operator++(int d)
    {
        // the body of the operator function
        // ...
    }

    // operator function that overloads the prefix operator -- (--X)
    type operator--()
    {
        // the body of the operator function
        // ...
    }

    // operator function that overloads the postfix operator -- (--X)
    type operator--(int d)
    {
        // the body of the operator function
        // ...
    }
};

 

3. An example of overloading operator functions ++ and in a class for single objects

The implementation of operator functions for the class Integer, which implements an integer value, is demonstrated.
The Integer class is declared, containing:

  • internal variable of integer type. This variable stores the integer value;
  • two constructors that initialize a variable ‘number’;
  • methods of accessing the variable number Get(), Set();
  • two operator functions that overload the ++ operator;
  • two operator functions that overload the operator.

The implementation of the Integer class is as follows:

// overloading increment operators for class Integer
class Integer
{
private:
    int number; // data member

public:
    // class constructors
    // constructor without parameters
    Integer() { number = 0; }

    // constructor with 1 parameter
    Integer(int _number) { number = _number; }

    // access methods
    void Set(int _number) { number = _number; }
    int Get(void) { return number; }

    // operator function that overloads
    // the prefix form of the operator ++ for the class Integer
    Integer operator++(void)
    {
        number++;
        return *this; // return the object of class
    }

    // operator function that overloads
    // postfix form of operator ++ for Integer class
    Integer operator++(int d) // parameter d is not used
    {
        number++;
        return *this;
    }

    // overloading of prefix --
    Integer operator--(void)
    {
        number--;
        return *this;
    }

    // overloading of postfix --
    Integer operator--(int d) // parameter d is not used
    {
        number--;
        return *this;
    }
};

The following is the use of the Integer class.

// demonstrating the use of overloaded increment operator functions
Integer d1, d2(5); // declaration of objects of class Integer
Integer d3;
int t1, t2;

// checking
t1 = d1.Get(); // t1 = 0
t2 = d2.Get(); // t2 = 5

// call the overloaded operator functions
++d1; // call the prefix operator function operator++()
t1 = d1.Get(); // t1 = 1

d2++; // call the postfix operator function operator++(int)
t2 = d2.Get(); // t2 = 6

--d1; // prefix --
d1--; // postfix --
t1 = d1.Get(); // t1 = -1

 

4. An example of overloading operator functions ++ and in classes that process arrays

The ArrayInt class is declared, which demonstrates the overloading of the prefix and postfix operator functions operator++() and operator–(), which respectively increase and decrease each element of the array by 5.
The ArrayInt class declaration is as follows:

// class that implements an array of integers
class ArrayInt
{
private:
    int A[100]; // internal variable - array of integers
    int size; // number of array items

public:
    // constructors
    ArrayInt() { size = 0; }

    ArrayInt(int _size)
    {
        if (_size>100) _size=100;
        size = _size;

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

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

    int GetAi(int index) { return A[index]; }
    int GetSize(void) { return size; }

    // overloaded operator ++
    // prefix form
    ArrayInt operator++(void)
    {
        for (int i=0; i<size; i++)
            A[i] = A[i] + 5;
        return *this;
    }

    // postfix form of operator ++, parameter t is not used
    ArrayInt operator++(int t)
    {
        for (int i=0; i<size; i++)
            A[i] = A[i] + 5;
        return *this;
    }

    // prefix form of operator --
    ArrayInt operator--(void)
    {
        for (int i=0; i<size; i++)
            A[i] = A[i] - 5;
        return *this;
    }

    // postfix form of operator --, parameter t is not used
    ArrayInt operator--(int t)
    {
        for (int i=0; i<size; i++)
            A[i] = A[i] - 5;
        return *this;
    }
};

The use of the ArrayInt class can be as follows

// demonstrating the use of overloaded incremental operator functions
ArrayInt AA(10);
int t;

// initialize the AA array with some values
for (int i=0; i<AA.GetSize(); i++)
    AA.SetAi(i, i+1);

// checking
t = AA.GetAi(2); // t = 3

// calling the overloaded operator functions
AA++;
t = AA.GetAi(2); // t = 3+5 = 8

--AA;
AA--;
t = AA.GetAi(2); // t = 8-5-5 = -2

 

5. Features of increment and decrement operators overloading using friendly functions

If the operators ++ and are overloaded with the help of friendly functions to the class, then the following should be considered:

  • the class-friendly function does not get the this class pointer;
  • since a friendly function does not receive a this pointer, a parameter to this function can be passed by reference, but not by value. This means that before the name of the parameter the reference symbol & is indicated.

 

6. Differences in overloading prefix and postfix increment operators (++) and decrement () using “friendly” functions

In order to distinguish the prefix and postfix forms of the implementation of the operator function ++ or in the implementation of a class-friendly function, the following rules must be followed:

  • if the prefix form of the operator ++ (++x) is overloaded, the “friendly” operator function should receive one parameter. This parameter is a reference to the class for which this function is implemented;
  • if the prefix operator form is overloaded (x), then the “friendly” operator function should receive one parameter, which is a reference to the class in which this function is implemented;
  • if the postfix form of the operator ++ (x++) is overloaded, then the “friendly” operator function receives two parameters. The first parameter is a reference to a friendly class. The second parameter is a formal parameter of an integer type, which serves as an indicator that it is the postfix, and not the prefix form of the operator ++, that is being overloaded. The second parameter in the function is not used;
  • if the postfix form of the operator is overloaded, then the friendly operator function receives two parameters. The first parameter is a reference to a friendly class. The second parameter is not used, but serves to determine what exactly the postfix form of the operator is implemented.

For example.

// class declaration
class SomeClass
{
    // data members and methods of class
    // ...

    // declaration of friendly functions for class SomeClass
    friend SomeClass operator++(SomeClass & ref); // ++x
    friend SomeClass operator--(SomeClass & ref); // --x
    friend SomeClass operator++(SomeClass & ref, int d); // x++
    friend SomeClass operator--(SomeClass & ref, int d); // x--
};

// the declaration of operator function,
// that overloads prefix operator ++ (++x)
SomeClass operator++(SomeClass & ref)
{
    // ...
}

// the declaration of operator function,
// that overloads prefix operator -- (--x)
SomeClass operator--(SomeClass & ref)
{
    // ...
}

// the declaration of operator function,
// that overloads postfix operator ++ (++x)
SomeClass operator++(SomeClass & ref, int d)
{
    // ...
}

// the declaration of operator function,
// that overloads postfix operator -- (x--)
SomeClass operator--(SomeClass & ref, int d)
{
    // ...
}

As you can see from the example, the friendly operator function receives a reference to the friendly class.

 

7. Examples of operator functions that overload the increment and decrement operators, and which are implemented as “friendly functions”

Example 1. Operators ++ and for the class Integer are overloaded with the help of friendly operator functions. Friendly operator functions are implemented outside the class.

// Integer class that implements an integer
class Integer
{
private:
    int number;

public:
    // class constructors
    Integer() { number = 0; }
    Integer(int _number) { number = _number; }

    // access methods
    int Get(void) { return number; }
    void Set(int _number) { number = _number; }

    // declaration of friendly operator functions
    friend Integer operator++(Integer & ref);
    friend Integer operator--(Integer & ref);
    friend Integer operator++(Integer & ref, int d);
    friend Integer operator--(Integer & ref, int d);
};

// implementation of friendly operator funcions
// ++x
Integer operator++(Integer & ref)
{
    ref.number++; // access by reference
    return ref;
}

// --x
Integer operator--(Integer & ref)
{
    ref.number--;
    return ref;
}

// postfix form - x++
Integer operator++(Integer & ref, int d)
{
    ref.number++;
    return ref;
}

// postfix form - x--
Integer operator--(Integer & ref, int d)
{
    ref.number--;
    return ref;
}

Using the Integer class in another method can be, for example, like this:

// friendly operator functions, overloading of operators ++, --
Integer d1, d2(8);
int t;

// checking
t = d1.Get(); // t = 0
t = d2.Get(); // t = 8

// calling the friendly operator functions
++d1; // friendly prefix operator function operator++()
d2--; // friendly postfix operator function operator--()

t = d1.Get(); // t = 1
t = d2.Get(); // t = 7

Example 2. The ++ and operators for the ArrayInt class are overloaded with the help of “friendly” operator functions. In the ArrayInt class, internal data, constructors, access methods, and class-friendly operator functions are declared.

Friendly operator functions overload the ++ and operators. Friendly operator functions increase or decrease by 1 the value of each item of the array, which is declared in the ArrayInt class.
The implementation of the ArrayInt class and “friendly” operator functions is as follows

// the ArrayInt class that implements an array of integers
class ArrayInt
{
private:
    int *A; // array of integers, the size of the array is arbitrary
    int size; // size of the array

public:
    // class constructors
    ArrayInt()
    {
        size = 0;
        A = NULL;
    }

    // constructor with 1 parameter
    ArrayInt(int _size)
    {
        size = _size;
        A = new int[size];

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

    // access methods
    int GetSize(void)
    {
        return size;
    }

    void SetSize(int _size)
    {
        // free the previous memory fragment
        if (size>0)
            delete[] A;

        // set the new size of the array
        size = _size;
        A = new int[size];

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

    int GetAi(int index)
    {
        return A[index];
    }

    void SetAi(int index, int value)
    {
        A[index] = value;
    }

    // friendly operator functions ++, --
    friend ArrayInt operator++(ArrayInt & AI);
    friend ArrayInt operator--(ArrayInt & AI);
    friend ArrayInt operator++(ArrayInt & AI, int d);
    friend ArrayInt operator--(ArrayInt & AI, int d);
};

// implementation of friendly operator functions ++, --
// ++x
ArrayInt operator++(ArrayInt & AI)
{
    // increase each item of the array by 1
    for (int i=0; i<AI.size; i++)
        AI.A[i] = AI.A[i] + 1; // access by reference
    return AI;
}

// --x
ArrayInt operator--(ArrayInt & AI)
{
    // decrease each item of the array by 1
    for (int i=0; i<AI.size; i++)
        AI.A[i] = AI.A[i] - 1; // access by reference
    return AI;
}

// x++
ArrayInt operator++(ArrayInt & AI, int d)
{
    // increase each item of the array by 1
    for (int i=0; i<AI.size; i++)
        AI.A[i] = AI.A[i] + 1; // access by reference
    return AI;
}

// x--
ArrayInt operator--(ArrayInt & AI, int d)
{
    // decreas each item of the array by 1
    for (int i=0; i<AI.size; i++)
        AI.A[i] = AI.A[i] - 1; // access by reference
    return AI;
}

The following demonstrates the use of the ArrayInt class and operator functions.

// friendly operator functions, overloading operators ++, --
ArrayInt A(10);
int t;

// setting arbitrary values in an array
for (int i=0; i<A.GetSize(); i++)
    A.SetAi(i, i+1); // A.A[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

// checking
t = A.GetAi(3); // t = 4
t = A.GetAi(5); // t = 6

// using of overloaded operators ++, --
A++; // postfix function operator++(ArrayInt, int)
t = A.GetAi(3); // t = 5
t = A.GetAi(5); // t = 7

--A;
--A;
t = A.GetAi(3); // t = 3
t = A.GetAi(5); // t = 5

++A;
++A;
++A;
t = A.GetAi(3); // t = 6

 


Related topics