Overloading operator indexing elements of the array

Overloading operator [] indexing elements of the array


Contents



1. What restrictions are imposed on operator [] overloading?

The following restrictions are imposed on operator [ ] overloading:

  • to this operator it is forbidden to apply “friendly” functions;
  • the operator function overloading this operator may be a non-static member function.

 

2. Overloading operator indexing elements of the array []. Features of use

In the C++ programming language, it is possible to overload the index operator of the elements of the array [ ]. This operator is considered unary, that is, it requires one parameter – the array index. So, it is advisable to overload the [ ] operator in classes where arrays are used.

If the [ ] operator is overloaded in a class that implements an array, then an object of this class can be used as a regular array (using access by index), which is very convenient and natural.

For example. Let a class named A be given. In the class, the array index operator [ ] is overloaded. Then the use of an instance of class A may be as follows:

obj[d]

where

  • obj – instance (object) of class A;
  • d is the index. This is a parameter that is passed to the operator function operator[]() of class A.

In the above example, the call

obj[d]

converted to a call

obj.operator[](d)

 

3. Variants of the operator function operator[]() in the class. General form

In order to overload the operator of indexing the elements of the array [], the operator function operator[]() must be implemented in the class. There are 2 ways to implement the operator function operator[]().These variants differ in returning a value from an operator function. The operator function receives one parameter, which is the array index.

Variant 1. This variant applies when the [] operator should only be used on the right side of an assignment operator. That is, the value of the array element in the class does not change.

In this case, the operator function operator[]() returns a value of some type. The general form of the function when it is implemented in the class

class ClassName
{

    // ...

    // operator function returns value of type
    type operator[](int d)
    {
        // ...
    }
};

After that, you can use an instance of the class ClassName as follows:

x = obj[3];

where

  • x – some type variable of type type;
  • obj – instance (object) of class ClassName.

Variant 2. This variant is used when it is necessary for the operator [] to be placed in the left and right part of the assignment operator. The presence of the indexing operator [] on the left side of the assignment operator means that in the class object you can change the values of the elements of the array by index.

The difference from the previous version (Variant 1) is that the function returns a reference & to the type. The general form of the declaration of an operator function is as follows.

class ClassName
{

    // ...

    // operator function returns reference (&) to type
    type& operator[](int d)
    {
        // ...
    }
};

After this declaration, you can use an instance of the class ClassName as follows:

// using operator [] for a class object
x = obj[3]; // on the right part of the assignment operator
obj[5] = y; // in the left part of the assignment operator

where

  • x – some type variable;
  • obj – instance (object) of class ClassName.

 

4. Examples of overloading the index operator [ ] of the array elements

Example 1. An example of overloading the [ ] operator in a class. The class implements an array of numbers of type int. The maximum number of elements in an array is 10. The operator function of a class returns a reference to the type int. This means that the operator [ ] can be used on the left side of an assignment operator.
In the class Array10 are declared:

  • A – internal array of 10 integers;
  • n – the number of items in the array;
  • class constructors;
  • method GetN(). This method is designed to get the value of n;
  • the SetAi() and GetAi() methods for accessing the items of array A;
  • operator function operator[](). This function overloads the operator of access to an array item by its index.

The text of the program is as follows:

#include <iostream>
using namespace std;

// class that implements an array of 10 integers
class Array10
{
private:
    int A[10]; // array
    int n; // number of items in the array

public:
    // class constructors
    // constructor without parameters
    Array10()
    {
        n = 0;
    }

    // constructor with 1 parameter
    Array10(int _n)
    {
        if ((_n >= 0) && (_n <= 10))
        {
            n = _n;
            for (int i = 0; i < n; i++)
                A[i] = 0;
        }
        else
            n = 0;
    }

    // array access methods
    // read the number of items in the array
    int GetN()
    {
        return n;
    }

    // write a value to array item
    void SetAi(int index, int item)
    {
        if ((index>=0)&&(index<10))
            A[index] = item;
    }

    // get the value of the index
    // internal method
    int GetAi(int index)
    {
        return A[index];
    }

    // overloading the operator [] to get the array item
    // operator function implemented inside a class
    int& operator[](int index)
    {
        return A[index];
    }
};

void main()
{
    // operator [] of indexing an array
    Array10 A1(10);

    // A1 = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    for (int i = 1; i <= 10; i++)
        A1[i - 1] = i; // a call to the operator function operator[]() of class Array10

    // checking
    int t;

    t = A1[3]; // invoke the operator function, t = 4

    // Operator [] on the left side of the assignment operator
    A1[5] = 205;
    t = A1.GetAi(5); // t = 205

    cout << "t = " << t << endl;
}

As you can see from the example, the operator function returns a reference to the int type

// operator function - returns int &
int& operator[](int index)
{
    return A[index];
}

This means that the operator [ ] can be used in the left part of the assignment operator

...

// Operator [] on the left part of the assignment operator
A1[5] = 205;

...

If an operator function is implemented so that it returns an int value (and not an int& reference)

// operator function - returns int
int operator[](int index)
{
    return A[index];
}

then using the operator [ ] in the left part of the assignment operator will be prohibited

...

// Operator [] on the left side of the assignment operator
A1[5] = 205; // error, it is forbidden!

t = A1[3]; // so it works

...

Example 2. Overloading the indexing operator [ ] of the elements of the array for an array of structures of type BOOK.

The example declares:

  • a structure of type BOOK containing information about the book;
  • class ArrayBooks, which implements a dynamic array of books of type BOOK.

In the class ArrayBooks are implemented:

  • internal variable-pointer to type BOOK;
  • internal variable n, which determines the number of books in the array;
  • two constructors;
  • a GetN() method that returns the number of books n in array;
  • the operator function operator[](). This function accesses a given item of the array. The function overloads the access operator by index [ ].

The text of the program created using the Console Application template is as follows:

#include <iostream>
#include <stdio.h>
using namespace std;

// structure describing a book
struct BOOK
{
    string title; // title of the book
    int year; // the year of publishing
    float price; // book cost
};

// class that implements an array of books of type BOOK
// it contains an overloaded operator function operator[]()
class ArrayBooks
{
private:
    BOOK * B; // memory for an array is dynamically allocated
    int n; // number of books

public:
    // class constructors
    ArrayBooks()
    {
        n = 0;
        B = NULL;
    }

    ArrayBooks(int _n)
    {
        n = _n;

        // allocate memory for pointers to BOOK
        B = (BOOK*) new BOOK[n];

        // fill each book with empty values
        for (int i=0; i<n; i++)
        {
            B[i].title = "";
            B[i].price = 0.00;
            B[i].year = 0;
        }
    }

    // destructor
    ~ArrayBooks()
    {
        // free the memory allocated for the array of structures
        if (n>0)
            delete[] B;
    }

    // method returning n
    int GetN(void) { return n; }

    // operator function that overloads the operator []
    // the function returns BOOK &, so that the [] operator can be used
    // in the left part of the assignment operator
    BOOK& operator[](int index)
    {
        if ((index>=0)&&(index<n))
            return B[index];
        else
        {
            // return the empty structure
            BOOK BB;
            BB.title = "";
            BB.price = 0.0;
            BB.year = 0;
            return BB;
        }
    }
};

void main()
{
    // demonstration of operator overloading []
    ArrayBooks AB(3); // create an ArrayBooks class object in an array of 3 items

    // invoke the operator function operator[](), generating the values
    // book - 1
    AB[0].title = "This is a first book";
    AB[0].price = 99.99;
    AB[0].year = 2999;

    // book - 2
    AB[1].title = "This is a second book";
    AB[1].price = 125.95;
    AB[1].year = 2020;

    // book - 3
    AB[2].title = "Third book";
    AB[2].price = 777.77;
    AB[2].year = 2000;

    // checking
    string title;
    double price;
    int year;

    title = AB[1].title; // title = "This is a second book"
    price = AB[1].price; // price = 125.95
    year = AB[1].year; // year = 2020

    // display
    cout << "Title = " << title.c_str() << ::endl;
    cout << "Price = " << price << ::endl;
    cout << "Year = " << year << ::endl;
}

The result of the program

Title = This is a second book
Price = 125.95
Year = 2020

 

5. What are the requirements for operator[]() operator function parameter?

The operator function, which overloads the indexing operator of the items of the array, receives a parameter that is an index in the array. The parameter type may not necessarily be an int. A different type of parameter is allowed in the array index (for example, char).

 

6. An example of a class that contains the operator function operator[](), whose index is of type char

This example demonstrates the statement that the type of an index in an operator function may not be just int.
The example implements the CharIndex class, which contains an array of 26 items. The class declares an operator function operator[](), which as an index receives a value of type char.

The program calculates the number of occurrences of the Latin alphabet characters ‘a’ .. ‘z’ in a given text.

The text of the program created using the Console Application template is as follows.

#include <iostream>
using namespace std;

// access by index in an operator function - class CharIndex
class CharIndex
{
private:
    int A[26]; // array of the number of occurrences of the character in the text

public:
    CharIndex()
    {
        for (int i=0; i<26; i++)
            A[i] = 0;
    }

    // operator function - access by type char
    int& operator[](char c)
    {
        int position; // position in array A
        position = (int)c - int('a');
        return A[position];
    }
};

void main(void)
{
    // demonstration of the statement
    // that the type of the index does not have to be an int
    CharIndex cI; // object of class CharIndex
    string text; // specified text
    int i;
    char sym;

    // some text is given
    text = "C++ is the best language in the world!";

    // calculate the number of occurrences of the characters 'a' .. 'z' in the text
    for (i = 0; i<text.length(); i++)
        cI[text[i]]++; // invoke the operator function

    // output, only nonzero values are output
    for (i=0; i<26; i++)
    {
        sym = 'a' + i; // take the index
        if (cI[sym]>0)
            cout << sym << " = " << cI[sym] << ::endl;
    }
}

The result of the program

a = 2
b = 1
d = 1
e = 4
g = 2
h = 2
i = 2
l = 2
n = 2
o = 1
r = 1
s = 2
t = 3
u = 1
w = 1

 


Related topics