Если у меня есть указатель на объект с перегруженным индексом ([]
), почему я не могу этого сделать:
MyClass *a = new MyClass();
a[1];
но нужно сделать это вместо:
MyClass *a = new MyClass();
(*a)[1];
Если у меня есть указатель на объект с перегруженным индексом ([]
), почему я не могу этого сделать:
MyClass *a = new MyClass();
a[1];
но нужно сделать это вместо:
MyClass *a = new MyClass();
(*a)[1];
Это потому, что вы не можете перегружать операторов для типа указателя; вы можете перегружать только оператор, где хотя бы один из параметров (операндов) имеет тип класса или тип перечисления.
Таким образом, если у вас есть указатель на объект некоторого типа класса, который перегружает оператор индекса, вы должны разыменовать этот указатель, чтобы вызвать его перегруженный оператор индекса.
В вашем примере a
имеет тип MyClass*
; это тип указателя, поэтому используется встроенный operator[]
для указателей. Когда вы разыгрываете указатель и получаете MyClass
, у вас есть объект типа класса, поэтому используется перегруженный operator[]
.
Потому что a
- это указатель на тип MyClass, а не MyClass. Изменение языка для поддержки вашего желаемого использования приведет к разрыву многих семантик языка.
Вы можете получить синтаксический результат, который вы хотите:
struct foo {
int a[10];
int& operator [](int i) { return a[i]; }
};
main() {
foo *a = new foo();
foo &b = *a;
b[2] = 3;
}
Проще говоря, с a[1]
указатель a
рассматривается как массив, содержащий память, и вы пытаетесь получить доступ к 2-му элементу массива (которого не существует).
(*a)[1]
заставляет сначала получить фактический объект в местоположении указателя, (*a)
, а затем вызвать на нем оператор []
.
Хорошие новости. Вы также можете сделать...
а- > оператор [] (1);
Чтобы добавить предпочтительный ответ, подумайте о перегрузке оператора как функции перегрузки.
При перегрузке функции-члена класса вы помните, что указатель не относится к типу этого класса.