Почему перегрузка оператора для указателей не позволяет работать?
В соответствии с комментарием в этом ответе ссылки были представлены в основном для поддержки перегрузки операторов, которая цитирует Bjarne Stroustrup:
Ссылки были представлены в первую очередь для поддержки перегрузки оператора. С передает каждый аргумент функции значение, и при прохождении объекта значение будет неэффективным или неприемлемый пользователь может передать указатель. Эта стратегия не работает где используется перегрузка оператора. В В этом случае необходимо, чтобы пользователь не мог ожидается вставить адрес если объекты большие.
Это означает, что перегрузка оператора не может работать с указателем. Но это не ясно объясняет, почему перегрузка оператора указателями не может работать. Почему бы не перегружать работу оператора указателями?
IMO, где используются ссылки, указатели также могут использоваться на своем месте.
Ответы
Ответ 1
Потому что, если бы это было разрешено, тогда это выглядело бы неплохо и не было бы столь же интуитивным, как его со ссылкой.
Предположим, что это разрешено, тогда вы должны написать:
struct A{};
A a, *pa, b;
a = pa ;//doesn't look good, also not intuitive. (not real C++)
Это не выглядит хорошо, потому что на левой стороне у вас нет указателя, справа - указатель. Выглядит очень странно. Кроме того, поскольку типы не совпадают, это не выглядит очень интуитивным относительно того, что именно он делает. Я имею в виду, что вы назначаете указатель на не указатель; что такое задание должно делать? Копирование содержимого адреса, на которое указывает указатель на пункт назначения (не указатель), не очень интуитивно понятен.
С другой стороны, поскольку это разрешено с ссылкой (реальность, а не предположение):
a = b; //looks good, intuitive, as now both side is same type
С ссылкой, у вас есть один и тот же тип, только когда b
передается в operator=()
в качестве аргумента, он передается по ссылке (или указывается указателем, так как ссылки являются синтаксическим сахаром указателей). избегайте ненужной копии, что, в свою очередь, не мешает производительности, поскольку она , если передается по значению.
Было бы также интересно отметить, что не только b
передается по ссылке (или указатель внизу), a
также передается функции указателем, потому что мы знаем в функции ключевое слово this
на самом деле является указателем.
Итак, ссылки были введены в С++, чтобы все выглядело хорошо и интуитивно понятно для программистов, иначе они будут указателями внизу. Фактически, большинство компиляторов реализуют ссылки с помощью указателей (указатель-механизм) внутри.
Ответ 2
Почему он не работает для указателей? Потому что это неоднозначно. Будет ли
ostream* operator<<(ostream* s, const char* c);
матч
cout << 'a';
или
cout << "a";
?
Кроме того, вы не можете использовать адрес (&
) с временным. Что это должно сделать:
complex<double> a, b, c;
cout << a + b * c;
так как b * c
является временным, и сумма также.
?
Ответ 3
Если оператор с плюсом перегружен для тяжелого класса, вам нужно будет написать либо a + b
(по значению, неэффективно), либо &a + &b
(уродливый и сложный), чтобы добавить два объекта этого класса. Но со ссылками вы получаете by-ref даже при написании a + b
.
Ответ 4
Поскольку большинство операторов уже имеют альтернативное установленное значение при применении к указателям.
Ответ 5
Оператор перегружает работу с объектами, но указатель сам по себе не является объектом. Он указывает на объект.
Ответ 6
Рассмотрим утверждение
c= a+b
где оператор + был перегружен.
Этот оператор может интерпретироваться компилятором как
c=operator+ (a, b)
Так как здесь адреса переменных не передаются, поэтому мы не можем их собирать в переменных указателя.
Если мы хотим собрать их в переменных указателя, тогда мы должны изменить оператор следующим образом:
c=&a+&b;
Но это означает, что мы пытаемся добавить адреса a и b, а не их значения. В такие моменты для сохранения памяти могут использоваться только ссылки.
Ответ 7
Операторы не могут быть перегружены, если задействованы оба типа типов (например, int
, float
или любой указатель). Вы можете перегрузить оператор для одного класса и одного примитивного типа (или просто использовать преобразование типов). Например, вы можете добавить std::string
и const char *
.
Ответ 8
Из этого следует, что оператор перегрузка не может работать с указателем.
Это не означает, что вообще. В нем говорится, что предоставление ссылок является существенным нотационным удобством, так что программисту не нужно свободно использовать адрес-оператора.
Также случается, что перегрузка оператора не работает с указателями, но в основном потому, что для нее нет синтаксиса. Зачем? Спросите Страустрапа.
Ваша ИМО правильная, если перед указателем используется оператор разыменования.
Ответ 9
Это 2019 год и у вас до сих пор нет доступа к классам нативных типов. Там нет никакого способа переопределить операторы на них.
Указатели (например, char, int, float и т.д.) Являются нативным типом. Вы можете создать объект, который ведет себя как указатель и операторы перегрузки [->, *], но он не будет перегружать [->, *] для собственного указателя. Вы также можете, например, создать объект, который ведет себя как int и перегружает [+, -, *,/], но не будет перегружать [+, -, *,/] в нативном int.
Для прагматического рационального, представьте хаос, если
this->member
имел пользовательское значение.
Ссылки - это не связанная тема, ИМХО.