Почему вы не можете перегрузить '.' оператора в С++?
Было бы очень полезно перегрузить. оператора в С++ и вернуть ссылку на объект.
Вы можете перегрузить operator->
и operator*
, но не operator.
Есть ли техническая причина для этого?
Ответы
Ответ 1
Смотрите эту цитату из Bjarne Stroustrup:
Оператор . (точка) в принципе может быть перегружена с использованием того же метод, используемый для → . Однако это может привести к возникновению вопросов о том, предназначена ли операция для перегрузки объекта. или объект, на который ссылается. Например:
class Y {
public:
void f();
// ...
};
class X { // assume that you can overload .
Y* p;
Y& operator.() { return *p; }
void f();
// ...
};
void g(X& x)
{
x.f(); // X::f or Y::f or error?
}
Эта проблема может быть решена несколькими способами. В момент стандартизации, было не очевидно, каким образом было бы лучше. Для большего подробности, см. Дизайн и эволюция С++.
Ответ 2
Stroustrup сказал, что С++ должен быть расширяемым, но не изменяемым языком.
Оператор точки (доступ к атрибутам) рассматривался как слишком близкий к ядру языка, чтобы разрешить перегрузку.
См. Проект и эволюция С++, с. 242, раздел 11.5.2. Интеллектуальные ссылки.
Когда я решил разрешить перегрузку оператора ->
, я, естественно, считал, что оператор .
может быть аналогичным образом перегружен.
В то время я считал следующие аргументы убедительными: если obj
- объект класса, то obj.m
имеет значение для каждого члена m
этого класса объекта. Мы стараемся не изменять язык путем переопределения встроенных операций (хотя это правило нарушено для =
из-за крайней необходимости и для унарного &
).
Если мы допустили перегрузку .
для класса X
, мы не смогли бы получить доступ к элементам X
обычными способами; мы должны были бы использовать указатель и ->
, но ->
и &
также могли быть переопределены. Мне нужен расширяемый язык, а не изменчивый.
Эти аргументы веские, но не окончательные. В частности, в 1990 году Джим Адкок предложил разрешить перегрузку оператора .
точно так же, как оператор ->
.
"Я" в этой цитате - Бьярне Страуструп. Вы не можете быть более авторитетными, чем это.
Если вы действительно хотите понять С++ (как в "почему это так" ), вы должны абсолютно прочитать эту книгу.
Ответ 3
Stroustrup имеет ответ на этот вопрос:
Оператор . (точка) может в принципе быть перегруженный с использованием той же используется для → . Однако это может приводят к операция предназначена для объекта перегрузка. или объект, упомянутый от. Например:
class Y {
public:
void f();
// ...
};
class X { // assume that you can overload .
Y* p;
Y& operator.() { return *p; }
void f();
// ...
};
void g(X& x)
{
x.f(); // X::f or Y::f or error?
}
Эта проблема может быть решена несколькими пути. Во время стандартизации, не было очевидно, каким образом Лучший. Для получения дополнительной информации см. D & E.
Ответ 4
Очень легко понять, если вы пройдете внутренний механизм вызова функции оператора,
Скажем, что класс классов может иметь два члена r для вещественной части и я для мнимой части.
Скажем Комплекс C1 (10,20), C2 (10,2)//мы предполагаем, что в классе уже есть конструктор с двумя аргументами.
Теперь, если вы пишете C1 + C2 в качестве инструкции, тогда компилятор попытается найти перегруженную версию оператора + на комплексном числе. Теперь предположим, что я перегружаю + оператор, поэтому
C1 + C2 внутренне переводится как c1.operator + (c2)
Теперь предположим, что у существ, которых вы можете перегрузить ". оператор.
поэтому теперь подумайте о следующем вызове C1.disp()//отображать содержимое сложного объекта. Теперь попробуйте представить как внутреннее представление
C1.operator. (------), создаются совершенно беспорядочные вещи. Вот почему мы не можем перегружать ". оператор