Почему вы не можете перегрузить '.' оператора в С++?

Было бы очень полезно перегрузить. оператора в С++ и вернуть ссылку на объект.

Вы можете перегрузить 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. (------), создаются совершенно беспорядочные вещи. Вот почему мы не можем перегружать ". оператор