When working with arrays, we typically use the subscript operator ([]) to index specific elements of an array:
myArray[0] = 7; // put the value 7 in the first element of the array
However, consider the following IntList class, which has a member variable that is an array:
class IntList
{
private:
int m_list[10]{};
};
int main()
{
IntList list{};
// how do we access elements from m_list?
return 0;
}
Because the m_list member variable is private, we can not access it directly from variable list. This means we have no way to directly get or set values in the m_list array. So how do we get or put elements into our list?
Without operator overloading, the typical method would be to create access functions:
class IntList
{
private:
int m_list[10]{};
public:
void setItem(int index, int value) { m_list[index] = value; }
int getItem(int index) const { return m_list[index]; }
};
While this works, it’s not particularly user friendly. Consider the following example:
int main()
{
IntList list{};
list.setItem(2, 3);
return 0;
}
Are we setting element 2 to the value 3, or element 3 to the value 2? Without seeing the definition of setItem(), it’s simply not clear.
You could also just return the entire list and use operator[] to access the element:
class IntList
{
private:
int m_list[10]{};
public:
int* getList() { return m_list; }
};
While this also works, it’s syntactically odd:
int main()
{
IntList list{};
list.getList()[2] = 3;
return 0;
}
Overloading operator[]
However, a better solution in this case is to overload the subscript operator ([]) to allow access to the elements of m_list. The subscript operator is one of the operators that must be overloaded as a member function. An overloaded operator[] function will always take one parameter: the subscript that the user places between the hard braces. In our IntList case, we expect the user to pass in an integer index, and we’ll return an integer value back as a result.
#include <iostream>
class IntList
{
private:
int m_list[10]{};
public:
int& operator[] (int index)
{
return m_list[index];
}
};
/*
// Can also be implemented outside the class definition
int& IntList::operator[] (int index)
{
return m_list[index];
}
*/
int main()
{
IntList list{};
list[2] = 3; // set a value
std::cout << list[2] << '\n'; // get a value
return 0;
}
Now, whenever we use the subscript operator ([]) on an object of our class, the compiler will return the corresponding element from the m_list member variable! This allows us to both get and set values of m_list directly.
This is both easy syntactically and from a comprehension standpoint. When list[2] evaluates, the compiler first checks to see if there’s an overloaded operator[] function. If so, it passes the value inside the hard braces (in this case, 2) as an argument to the function.
Note that although you can provide a default value for the function parameter, actually using operator[] without a subscript inside is not considered a valid syntax, so there’s no point.
