Операторы перегрузки как функция-член или функция не-члена (друга)?

в настоящее время я создаю класс утилиты, в котором будут перегружены операторы. Каковы плюсы и минусы того, чтобы сделать их членом или не членом (friend) функции? Или вообще разница? Может быть, для этого есть лучшая практика?

6 ответов


каждый оператор имеет свои собственные соображения. Например, оператор

Что касается разрешения специализации через наследование, общим шаблоном является реализация оператор-нечлен в терминах виртуальной функции-члена (например, оператор


Я бы пошел с "стандартами кодирования C++: 101 правила, рекомендации и рекомендации": Если вы можете сделать это как функция, не являющаяся членом, сделайте это как функция, не являющаяся членом (в том же пространстве имен).

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

другая причина: меньше соединения. Не-члены-функции менее тесно связаны, чем функции-члены. Это почти всегда хорошо.


если вы планируете реализовать операторы потоковой передачи (>), то они будут методами, не являющимися членами, потому что ваш объект находится слева от оператора.

если вы планируете реализовать ->, () или [] они, естественно, методы-члены.

для других (сравнение и математические) вы должны проверить импульс.Операторы, это действительно помогает.

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

MyClass& MyClass::operator+=(int);
MyClass operator+(const MyClass&, int);
MyClass operator+(int, const MyClass&);

вы только надо написать:

class MyClass: boost::operator::addable<MyClass,int> // no need for public there
{
public:
  MyClass& operator+=(int);
private:
};

в 2 operator+ будет автоматически сгенерирован как нечлены, которые позволят вам воспользоваться автоматическими преобразованиями. И они будут эффективно реализованы в срок operator+= таким образом, вы пишете код только один раз.


Если вы реализуете op, то, скорее всего, вам нужно реализовать op=. т. е. если вы перегружаете оператор+, то вы должны реализовать +=. Убедитесь, что вы возвращаете const объекту, если вы выполняете post-increment или перегрузку + operator. Итак , если вы перегрузите operator+, то реализуйте его как оператор, не являющийся членом, и используйте оператор += внутри него. Для EG.

const A operator+(const A& lhs, const A& rhs)
{
   A ret(lhs);
   ret += rhs;
   return ret;
}

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

рассмотрим простой класс string:

class str
{
public:
    str(const char *);
    str(const str &other);
};

Если вы реализуете operator+ как функцию-член, в то время как str("1") + "2" будет компилироваться, "1" + str("2") не будет компилироваться.

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


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

для e.г.

  1. >> и не может быть перегружен как функции-члены .

  2. Предположим, вы хотите сделать так:obj1 = 2 * obj2 перейти к функция, не являющаяся членом.

на бинарные перегрузку операторов функции-члена принимает только 1 параметр (вызов объекта impcliitly передается), в то время как функция, не являющаяся членом, принимает 2 параметра .