Почему перегрузка операторов для указателей не может работать? - PullRequest
15 голосов
/ 30 мая 2011

Согласно комментарию под этим ответом , ссылки были введены в первую очередь для поддержки перегрузки операторов, которая цитирует Бьярна Страуструпа:

Ссылки были введены в первую очередь для поддержки перегрузки оператора. С передает каждый аргумент функции значение, и где передача объекта по значение будет неэффективным или неуместно пользователь может передать указатель. Эта стратегия не работает где используется перегрузка оператора. В В этом случае нотационное удобство важно, чтобы пользователь не мог ожидается, чтобы вставить адрес- из операторы, если объекты большие.

Что означает, что перегрузка оператора не может работать с указателем. Но это не ясно объясняет, почему перегрузка операторов с помощью указателей не может работать. Почему перегрузка операторов не работает для указателей?

ИМО, где используются ссылки, вместо них можно использовать указатели.

Ответы [ 9 ]

7 голосов
/ 30 мая 2011

Потому что, если бы это было разрешено, то это не выглядело бы хорошо и не было бы таким же интуитивно понятным, как и со ссылкой.

Предположим, что это разрешено, тогда вы бы написали:

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 на самом деле является указателем .

Итак, ссылки были введены в C ++, чтобы все выглядело хорошо и интуитивно понятно для программистов, в противном случае они указатели внизу.Фактически, большинство компиляторов реализуют ссылки, используя указатели (механизм-указатель) внутри.

5 голосов
/ 30 мая 2011

Почему это не работает для указателей?Потому что это неоднозначно.

ostream* operator<<(ostream* s, const char* c);

будет соответствовать

cout << 'a';

или

cout << "a";

?

Кроме того, вы не можете использовать address-of (&) с временным.Что это должно сделать:

complex<double> a, b, c;
cout << a + b * c;

, поскольку b * c является временным, и сумма также.

?

1 голос
/ 15 ноября 2013

Рассмотрим утверждение

c= a+b         

, где оператор + был перегружен. Это утверждение может быть интерпретировано компилятором как

c=operator+ (a, b)

Поскольку здесь адреса переменных не передаются, поэтому мы не можем собирать их в переменные-указатели.

Если мы хотим собрать их в переменные-указатели, мы должны изменить оператор следующим образом:

c=&a+&b;

Но это означает, что мы пытаемся добавить адреса a и b, а не их значения. В такие моменты для экономии памяти могут использоваться только ссылки.

1 голос
/ 30 мая 2011

Операторская перегрузка работает на объектах , но указатель сам по себе не является объектом. Он указывает на объект.

1 голос
/ 30 мая 2011

Поскольку большинство операторов уже имеют альтернативное установленное значение применительно к указателям.

1 голос
/ 30 мая 2011

С оператором «плюс», перегруженным для тяжелого класса, вам придется написать либо a + b (по значению, неэффективно), либо &a + &b (безобразно и сложно), чтобы добавить два объекта этого класса.Но со ссылками вы получаете by-ref даже при написании a + b.

0 голосов
/ 11 июля 2019

Это 2019 год, и у вас все еще нет доступа к классам нативных типов. Нет возможности переопределить операторы на них.

Указатели являются (например, char, int, float и т. Д.) Родным типом. Вы можете создать объект, который ведет себя как указатель и операторы перегрузки [->, *], но он не будет перегружать [->, *] для встроенного указателя. Вы также можете, например, создать объект, который ведет себя как int и перегрузит [+, -, *, /], но не будет перегружать [+, -, *, /] в собственном int.

Для прагматичной рациональности представьте хаос, если

this->member

имел пользовательское значение.

Ссылки - это не связанная тема, ИМХО.

0 голосов
/ 31 мая 2011

Что подразумевает этот оператор перегрузка не может работать с указателем.

Это совсем не значит. заявляет , что предоставление ссылок является важным условным обозначением, так что программисту не нужно свободно использовать оператор address-of.

также - случай, когда перегрузка оператора не работает с указателями, но это в основном потому, что для него нет синтаксиса. Зачем? Спроси Страуструпа.

Ваш ИМО правильный, если перед указателем используется оператор разыменования.

0 голосов
/ 30 мая 2011

Операторы не могут быть перегружены, когда оба типа являются встроенными (например, int, float или любой вид указателя).Вы можете перегрузить оператор для одного класса и одного примитивного типа (или вы можете просто использовать преобразование типов).Например, вы можете добавить std::string и const char *.

...