Почему вы не можете перегрузить '.' оператор в C++?
Было бы очень полезно иметь возможность перегружать. оператор в C++ и вернуть ссылку на объект.
Вы можете перегрузить operator->
а также operator*
но нет operator.
Есть ли техническая причина для этого?
4 ответа
Смотрите эту цитату из Бьярне Страуструпа:
Оператор (точка) может быть в принципе перегружена с использованием той же техники, что и для ->. Однако это может привести к возникновению вопросов о том, предназначена ли операция для перегрузки объекта. или объект, на который ссылается. Например:
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? }
Эта проблема может быть решена несколькими способами. Во время стандартизации не было очевидно, какой путь будет наилучшим. Для получения дополнительной информации см . Дизайн и развитие C++.
Страуструп сказал, что C++ должен быть расширяемым, но не изменяемым языком.
Оператор точки (доступа к атрибуту) считался слишком близким к ядру языка, чтобы допустить перегрузку.
См . Дизайн и развитие C++, стр. 242, раздел 11.5.2 Умные ссылки.
Когда я решил разрешить перегрузку оператора
->
Я естественно считал ли оператором.
может быть так же перегружен.В то время я считал следующие аргументы убедительными:
obj
тогда объект классаobj.m
имеет значение для каждого членаm
класса этого объекта. Мы стараемся не делать язык изменчивым, переопределяя встроенные операции (хотя это правило нарушается для=
по острой необходимости, и для одинарных&
).Если бы мы допустили перегрузку
.
для классаX
мы не сможем получить доступ к членамX
обычными средствами; мы должны были бы использовать указатель и->
, но->
а также&
возможно, также был переопределен. Я хотел расширяемый язык, а не изменчивый.Эти аргументы веские, но не окончательные. В частности, в 1990 году Джим Адкок предложил разрешить перегрузку оператора
.
именно так, как оператор->
является.
"Я" в этой цитате - Бьярн Страуструп. Вы не можете быть более авторитетным, чем это.
Если вы хотите по-настоящему понять C++ (например, "почему это так"), вам обязательно следует прочитать эту книгу.
У Страуструпа есть ответ на этот вопрос:
Оператор (точка) может быть в принципе перегружена с использованием той же техники, что и для ->. Однако это может привести к возникновению вопросов о том, предназначена ли операция для перегрузки объекта. или объект, на который ссылается. Например:
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.
Это очень легко понять, если вы пройдете через внутренний механизм вызова операторной функции, скажем, комплексный класс может иметь два члена r для вещественной части и i для мнимой части. Скажем Complex C1 (10,20), C2 (10,2) // мы предполагаем, что в классе уже есть конструктор с двумя аргументами. Теперь, если вы напишите C1+C2 как оператор, то компилятор попытается найти перегруженную версию оператора + по комплексному числу. Теперь мы предполагаем, что я перегружаю + оператор, поэтомуC1+C2 внутренне переводится как c1.operator+(c2). Теперь предположим, что для существ времени вы можете перегрузить '.' оператор. так что теперь подумайте о следующем вызове C1.disp ()// отобразите содержимое сложного объекта. Теперь попробуйте представить как внутреннее представление C1.operator. (------), совершенно беспорядочные вещи, созданные. Вот почему мы не можем перегружать ". оператор