Оператор индексирования

Последнее обновление: 12.03.2023

Оператор индексирования [] (subscript operator) позволяет интерпретировать объект как массив или как контейнер других объектов и позволяет выбирать из объекта отдельные элементы. Функция оператора [] должна принимать в качестве аргумента условный индекс, по контрому в объекте-контейнере можно найти нужный элемент. Рассмотрим простейшей пример:

#include <iostream>

class Person
{
public:
    Person(std::string p_name, unsigned p_age, std::string p_company)
    {
        name = p_name;
        company = p_company;
        age = p_age;
    }
    std::string operator[](unsigned index) const
    {
        switch (index)
        {
            case 0: return name;
            case 1: return std::to_string(age);	// преобразуем в тип std::string
            case 2: return company;
            default: return "Bad Index";
        }
    }
private:
    std::string name;
    unsigned age;
    std::string company;
};

int main()
{
    Person tom{"Tom", 38, "Microsoft"};
    std::cout << tom[0] << "\n" << tom[1] << "\n" << tom[2] << std::endl;
}

Здесь класс Person определяет три приватных переменных - name, age и company, которые недоступны из вне. Фактически мы можем рассматривать объект Person как контейнер над этими переменными. И для обращения к ним определяем оператор индексации:

std::string operator[](unsigned index) const
{
    switch (index)
    {
        case 0: return name;
        case 1: return std::to_string(age);
        case 2: return company;
        default: return "Bad Index";
    }
}

Оператор в качестве операнда принимает числовой индекс, в данном случае типа unsigned (некоторое положительное целое число) и в зависимости от этого индекса возвращает значение определенной переменной. В данном случае возвращаем значение типа std::string, для этого значение поля age приводим к строке с помощью функции std::to_string. Значение какой именно переменной возвращать по тому или иному индексу условно. В данном случае логично (но необязательно) сделать это в порядке объявления переменных в классе. Затем в функции main, используя данный оператор, можно обратиться к определенной переменной через индекс:

Person tom{"Tom", 38, "Microsoft"};
std::cout << tom[0] << "\n" << tom[1] << "\n" << tom[2] << std::endl;

Консольный вывод:

Tom
38
Microsoft

Причем необязательно использовать именно числовые индексы. Они могут представлять любой тип, например, std::string:

#include <iostream>

class Person
{
public:
    Person(std::string p_name, unsigned p_age, std::string p_company)
    {
        name = p_name;
        company = p_company;
        age = p_age;
    }
    // строковый индекс
    std::string operator[](const std::string& prop) const
    {
        if(prop=="name") return name;
        else if(prop== "age") return std::to_string(age);
        else if(prop=="company") return company;
        else return "Bad Index"; 
    }
private:
    std::string name;
    unsigned age{};
    std::string company;
};

int main()
{
    Person tom{"Tom", 38, "Microsoft"};
    std::cout << tom["name"] << ": " << tom["company"] << std::endl;	// Tom: Microsoft
}

Оператор индексации можно использовать для доступа к элементам из набора, который может быть в объекте. Например, компания имеет набор сотрудников:

#include <iostream>
 
class Company
{
public:
    std::string& operator[](unsigned index)
    {
        return employees[index];
    }
private:
    std::string employees[10]{"Tom", "Sam", "Bob"};
};

int main()
{
    Company company;
    std::cout << company[0] << std::endl;	// Tom
    company[0] = "Tomas";
    std::cout << company[0] << std::endl;	// Tomas
}

Для простоты класс Company содержит набор сотрудников в виде массива строк. С помощью функции индексации мы можем обратиться к одному из элементов массива employees. Чтобы можно было изменять возвращенные объекты, оператор возвращает не просто объект std::string, а именно ссылку std::string&.

Однако главная проблема здесь заключается в организации логики возвращения элемента. В первом случае (в случае с классом Person) необходимо разнотипные значения приводить к единому типу. Во втором случае мы можем столкнуться с ситуацией, что будет передан недействительный индекс. На этот счет есть разные стратегии, но в любом случае подобные ситуации надо иметь в виду при определении оператора.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850