c++ поля Почему перегруженные операторы не могут быть определены как статические члены класса?



может ли не статический класс содержать статические поля или методы (5)

hmmm ... Я думаю о статическом операторе (), который бы однозначно удалял все конструкторы ... Это дало бы нам типизированные функции. Иногда мне жаль, что у нас это было на C ++.

https://ffff65535.com

Синтаксис C ++ позволяет определять перегруженные операторы либо внутри struct / class, например:

struct X
{
   void operator+(X);
}

или вне структуры / класса, например:

void operator+(X, X);

но не как

struct X
{
   static void operator+(X, X);
}

Означает ли какой-либо орган причины этого решения? Почему третья форма не разрешена? (MSVC дает синтаксическую ошибку). Может быть, за этим стоит какая-то история?

ps Присутствие первого и второго определений в то же время создает двусмысленность:

1>CppTest1.cxx
1>c:\ballerup\misc\cf_html\cpptest1.cxx(39) : error C2593: 'operator +' is ambiguous
1>        c:\ballerup\misc\cf_html\cpptest1.cxx(13): could be 'void B1::operator +(B1 &)'
1>        c:\ballerup\misc\cf_html\cpptest1.cxx(16): or       'void operator +(B1 &,B1 &)'
1>        while trying to match the argument list '(B1, B1)'

Я не понимаю, почему эта двусмысленность лучше, чем между 1,3 или 2,3.


В принципе, статический оператор класса не покупает ничего над нестатическим членом.

Любой оператор, определенный для класса, должен принимать хотя бы один аргумент этого типа класса.

Оператор-член принимает этот аргумент в виде неявного this параметра.

Оператор, не являющийся членом, имеет явный аргумент этого типа класса.

Интерфейс оператора к функции оператора не волнует; когда мы вызываем a + b , он заботится о генерации кода для передачи либо через this параметр, либо как явно объявленный параметр. Поэтому мы не выражаем никакой разницы в нюансах со статическими и нестационарными относительно использования оператора.

Предположим, что неожиданно появилось требование о том, что последний ISO C ++ должен поддерживать статические операторы-члены. В спешке это требование может быть реализовано путем перезаписи источника в источник в соответствии со следующим шаблоном:

static whatever class::operator *(class &x) { x.fun(); return foo(x); }

-->

whatever class::operator *() { (*this).fun(); return foo(*this); }

-->

whatever class::operator *() { fun(); return foo(*this); }

Компилятор переписывает static оператор-член в нестатический, удаляет самый левый параметр и (с надлежащей лексической гигиенической коррекцией) заменяет все ссылки на этот параметр выражением *this (ненужное использование которого может быть отменено).

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

Механизм определения static функции оператора менее эффективен. Например, он не может быть virtual , тогда как нестатический.


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

Конечно, если какой-то перегруженный оператор принимает класс C в качестве основного аргумента, нет веской причины, чтобы он был статическим членом класса C. Он может быть просто нестационарным членом, поэтому он неявно получает этот аргумент.

Однако статический член класса C может быть перегружен оператором в каком-либо классе, отличном от C.

Скажем, что существует operator ==(const widget &, const widget &); области видимости файла operator ==(const widget &, const widget &); , В моем классе squiggle я работаю с объектами widget , но хочу получить для них другое сравнение.

Я должен был бы сделать static squiggle::operator == (const widget &, const widget &); для меня.

Из области класса это легко назвать:

void squiggle::memb(widget a, widget b)
{
   if (a == b) { ... } // calls static == operator for widgets
}

из-за пределов класса, мы можем вызвать его только с явным разрешением разрешения в сочетании с явным синтаксисом операторских вызовов:

void nonmemb(widget a, widget b)
{
   a == b;  // calls the widget member function or perhaps nonstatic operator
   squiggle::operator ==(a, b); // calls squiggle class' utility
}

Это неплохая идея. Кроме того, мы можем сделать это с регулярными перегруженными функциями, а не с операторами. Если сравнение виджетов выполняется с помощью функции compare , тогда может быть не-элементный compare или widget::compare и может быть squiggle::compare который принимает widgets .

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

Возможно, это не достаточно полезная идея, чтобы гарантировать поддержку (до сих пор!). В конце концов, это не то, что позволило бы какую-то революционную реорганизацию C ++-программы. Но это исправило бы неполноту в языке.

Также учтите, что перегрузки классов операторов new и delete неявно статичны ! Таким образом, незавершенность уже имеет небольшое исключение.


У меня нет конкретных знаний о любом обсуждении этого понятия на C ++, поэтому не стесняйтесь игнорировать это.

Но для меня у вас есть вопрос назад. Вопрос должен состоять в следующем: «Почему этот синтаксис разрешен

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

Это не облегчает реализацию асимметричных операторов (т. operator+(const X &x, const Y &y) ). Если вам нужен частный доступ для реализации этого, вам все равно потребуется объявление друга для них в одном из классов.

Поэтому я бы сказал, что причина, по которой она не существует, заключается в том, что она не нужна . Между функциями, не являющимися членами, и нестационарными членами, рассматриваются все необходимые варианты использования.

Или, говоря иначе:

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

Благодаря использованию бесплатных функций вы можете получить зависящий от аргументов поиск для операторов, используемых в шаблонах. Вы не можете делать это со статическими функциями, потому что они должны быть членами определенного класса. И вы не можете добавить класс извне класса, в то время как вы можете добавить в пространство имен. Поэтому, если вам нужно поставить оператор в определенное пространство имен, чтобы сделать некоторый код ADL, вы можете. Вы не можете сделать это с помощью операторов статических функций.

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

что позволило бы использовать функторы без их создания?

Это противоречие в терминах. «Функтор» - это «функциональный объект». Тип не является объектом ; поэтому он не может быть функтором. Это может быть тип, который при создании экземпляра приведет к функтору. Но сам тип не будет функтором.

Кроме того, возможность объявить Typename::operator() не означает, что Typename() будет делать то, что вы хотите. Этот синтаксис уже имеет реальное значение: создать экземпляр временного имени, вызвав конструктор по умолчанию.

Наконец, даже если бы все это было не так, что бы это было на самом деле? Большинство функций шаблона, которые принимают вызываемый некоторый тип, работают так же хорошо, как указатель на функцию, как с функтором. Почему вы хотите ограничить свой интерфейс, а не просто функторами, а функторами, которые не могут иметь внутренние данные? Это означает, что вы не сможете пройти захват лямбда и т. Д.

Какая польза от функтора, который не может содержать состояние? Почему вы хотите заставить пользователя передавать «функторы», которые не имеют состояния? И почему вы хотите, чтобы пользователь не мог использовать лямбда?

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


Я не знаю о каких-либо прямых недостатках, которые могут привести к статическому оператору + (возможно, мышление достаточно долго приведет к некоторой теории). Но я думаю, что по крайней мере принцип «не платите за то, что вы не используете», объявленный Бьярном Страуступом, уже является достаточно хорошим ответом. Что вы получите, если этот статический оператор будет разрешен, за исключением более сложного синтаксиса (вам придется писать «X :: operator +» везде, а не просто «+»)?





static-methods