Разница между глобальным оператором и оператором-членом

Зачем вам когда-нибудь хотеть X& x = getx();? Просто используйте X x = getx(); и полагайтесь на RVO.

38
задан Gordon Gustafson 17 July 2009 в 19:42
поделиться

4 ответа

Одна из причин использования операторов, не являющихся членами (обычно объявляемых как друзья), заключается в том, что левая сторона - это та, которая выполняет операцию. Obj :: operator + подходит для:

obj + 2

, но для:

2 + obj

не работает. Для этого вам понадобится что-то вроде:

class Obj
{
    friend Obj operator+(const Obj& lhs, int i);
    friend Obj operator+(int i, const Obj& rhs);
};

Obj operator+(const Obj& lhs, int i) { ... }
Obj operator+(int i, const Obj& rhs) { ... }
47
ответ дан 27 November 2019 в 02:38
поделиться

Подводя итог ответу Codebender:

Операторы-члены не симметричны. Компилятор не может выполнять одинаковое количество операций с левыми и правыми операторами.

struct Example
{
   Example( int value = 0 ) : value( value ) {}
   int value;

   Example operator+( Example const & rhs ); // option 1
};
Example operator+( Example const & lhs, Example const & rhs ); // option 2
int main()
{
   Example a( 10 );
   Example b = 10 + a;
}

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

В общем, общий шаблон реализует операторы, которые должны быть функциями-членами как члены, а остальные как свободные функции, которые делегируют операторам-членам:

class X
{
public:
   X& operator+=( X const & rhs );
};
X operator+( X lhs, X const & rhs )
{
   lhs += rhs; // lhs was passed by value so it is a copy
   return lhs;
}
6
ответ дан 27 November 2019 в 02:38
поделиться

Самый разумный вариант - сделать его функцией друга .

Как упоминает JaredPar, глобальная реализация не может получить доступ к защищенным и частным членам класса, но есть проблема с функция-член тоже.

C ++ допускает неявное преобразование параметров функции, но не позволяет неявное преобразование this .

Если существуют типы, которые можно преобразовать в ваш класс X:

class Y
{
public:
    operator X();  // Y objects may be converted to X
};


X x1, x2;
Y y1, y2;

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

x1 == x2;   // Compiles with both implementations
x1 == y1;   // Compiles with both implementations
y1 == x1;   // ERROR!  Member function can't convert this to type X
y1 == y2;   // ERROR!  Member function can't convert this to type X

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

class X
{
    int value;

public:

    friend bool operator==( X& left, X& right ) 
    {
        return left.value == right.value;
    };
};
9
ответ дан 27 November 2019 в 02:38
поделиться

Есть по крайней мере одно отличие. Оператор-член подлежит модификаторам доступа и может быть публичным, защищенным или частным. Глобальная переменная-член не подлежит ограничениям модификатора доступа.

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

class Foo { 
  ...
private:
  Foo& operator=(const Foo&); 
};

Вы можете добиться того же эффекта, объявив единственный глобальный оператор. Но это привело бы к ошибке ссылки вместо ошибки компиляции (nipick: да, это привело бы к ошибке ссылки в Foo)

5
ответ дан 27 November 2019 в 02:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: