Разве нельзя вызывать операторы C ++ вручную? - PullRequest
14 голосов
/ 29 августа 2011

Я пытаюсь понять операторы в C ++ более тщательно.

Я знаю, что операторы в C ++ - это просто функции. Чего я не понимаю, так это как выглядит функция?

Взять например:

int x = 1;
int y = 2;
int z = x + y;

Как переводится последняя строка? Это:

1. int z = operator+(x,y);

или

2. int z = x.operator+(y);

Когда я попробовал оба из них, ошибки компилятора. Я неправильно их называю или операторы в C ++ не могут вызываться напрямую?

Ответы [ 6 ]

17 голосов
/ 29 августа 2011

При использовании C ++ standardese синтаксис вызова функции (operator+(x, y) или x.operator+(y)) работает только для операторских функций :

13.5 Перегруженные операторы [более.опер]

4. Операторские функции обычно не вызываются напрямую;вместо этого они вызываются для оценки операторов, которые они реализуют (13.5.1 - 13.5.7).Однако их можно явно вызывать, используя operator-function-id в качестве имени функции в синтаксисе вызова функции (5.2.2).[ Пример:

    complex z = a.operator+(b); // complex z = a+b;
    void* p = operator new(sizeof(int)*n);

- конец примера ]

И операторские функции требуют как минимум один параметр, который является типом классаили тип перечисления:

13.5 Перегруженные операторы [over.oper]

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

Это подразумеваетчто операторная функция operator+(), которая принимает только int s, не может существовать в 13.5 / 6.И вы, очевидно, не можете использовать синтаксис вызова функции для операторской функции, которая не может существовать.

9 голосов
/ 29 августа 2011

Для основных типов, таких как int, float, double; операторы уже перегружены / предопределены, поэтому ничего особенного для этого сделать нельзя. И,

int z = x + y;

это единственный способ выразить / позвонить.

Для цели интерпретации , фактически оба утверждения,

int z = operator+(x,y);
int z = x.operator+(y);

верно (если бы оно было перегружено).

6 голосов
/ 29 августа 2011

Операторские перегрузки применяются только к объектам и структурам, а не к фундаментальным типам (таким как int или float).Если у вас был класс объекта, такой как:

  class A {
    A operator+(const A& rhs) {
      return someComputedValue;
    }
  }

, тогда вы действительно можете вызвать myA.operator+(anotherA), и это будет эквивалентно myA + anotherA.

2 голосов
/ 29 августа 2011

Вы не можете перегружать бинарные операторы, когда оба аргумента встроены в типы. Однако для ваших собственных объектов это то, как вы можете их создавать.

//Simple struct that behaves like an int.
struct A
{
  int v_;
  explicit A(int i) : v_(i) {}  
  // A member operator so we can write a+b
  A operator+(const A & a ) const { return A( v_ + a.v_); }      
};

// A non-member operator, so we can write 1+a
A operator+(int i, const A & a)
{
   return A(i+a.v_);
}

int main()
{
  A a(1);
  A b(2);

  // Call the member version using its natural syntax    
  A c = a+b;
  //Call the member version using function call syntax
  A d = a.operator+(b);
  // Call the non-member version using the natural syntax
  A e = 1 + b;
  // Call the nonmember version using function call syntax.
  A f = ::operator+(1,b);
}
1 голос
/ 29 августа 2011

Как уже упоминалось в комментариях и других ответах, для operator+ не существует фундаментальных типов. Для классов ответ на вопрос, какой из operator+(x,y) против x.operator+(y) является правильным, «зависит». В частности, это зависит от того, как было определено operator+. Если она была определена как функция-член, вам нужно использовать x.operator+(y). Если она была определена как глобальная функция, вам нужно использовать operator+(x,y).

Когда компилятор сталкивается с оператором z=x+y;, ваш компилятор достаточно умен, чтобы искать соответствующую форму. Вы не должны ожидать того или другого. Вы должны использовать x+y.

1 голос
/ 29 августа 2011

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

Так что ни operator+(x, y) ни x.operator+(y) является правильным.Я полагаю, что x.operator+(y) менее корректно, потому что не struct типы не могут иметь членов, но я сомневаюсь, что это очень помогает.

...