Невозможно ли вызывать операторы С++ вручную?
Я пытаюсь понять операторы на С++ более тщательно.
Я знаю, что операторы в С++ в основном являются просто функциями. Я не понимаю, как выглядит функция?
Возьмем, например:
int x = 1;
int y = 2;
int z = x + y;
Как переводит последнюю строку? Это:
1. int z = operator+(x,y);
или
2. int z = x.operator+(y);
?
Когда я попробовал оба из них, ошибки компилятора. Я называю их неправильными или операторы на С++ не могут быть вызваны напрямую?
Ответы
Ответ 1
Используя С++ standardese, синтаксис вызова функции (operator+(x, y)
или x.operator+(y)
) работает только для функций оператора:
13.5 Перегруженные операторы [over.oper]
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);
-end пример]
И для функций оператора требуется хотя бы один параметр, который является типом класса или типом перечисления:
13.5 Перегруженные операторы [over.oper]
6. Функция оператора должна быть либо нестатической функцией-членом или быть нечленой функцией и иметь хотя бы один параметр, тип которого это класс, ссылка на класс, перечисление или ссылка на перечисление.
Это означает, что операторная функция operator+()
, которая принимает только int
, не может существовать на 13.5/6. И вы, очевидно, не можете использовать синтаксис вызова функции для функции оператора, которая не может существовать.
Ответ 2
Для базовых типов, таких как int
, float
, double
; операторы уже перегружены/предварительно определены, поэтому для этого ничего особенного не может быть сделано. И,
int z = x + y;
- это единственный способ выразить/назвать его.
Для цели интерпретации, фактически оба оператора,
int z = operator+(x,y);
int z = x.operator+(y);
являются истинными (если бы они были перегружены).
Ответ 3
Перегрузки оператора применяются только к объектам и структурам, а не к фундаментальным типам (например, int или float). Если у вас есть класс объектов, например:
class A {
A operator+(const A& rhs) {
return someComputedValue;
}
}
то вы действительно можете вызвать myA.operator+(anotherA)
, и это будет эквивалентно myA + anotherA
.
Ответ 4
Вы не можете перегружать двоичные операторы, когда оба аргумента построены в типах.
Однако для ваших собственных объектов вы можете их создать.
//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);
}
Ответ 5
Для родных типов операторы не являются функциями. Функционируют только перегруженные операторы. Встроенные операторы встроены - у них нет "функций", они обычно просто компилируются до одной или двух команд сборки, которые было бы безумным, чтобы вызывать функцию.
Таким образом, ни operator+(x, y)
, ни x.operator+(y)
не верны. Я полагаю, что x.operator+(y)
менее корректен, потому что типы не struct
не могут иметь членов, но я сомневаюсь, что это помогает.
Ответ 6
Как уже упоминалось в комментариях и в других ответах, для основных типов нет operator+
. Для классов правильный ответ на вопрос о том, какой из operator+(x,y)
по сравнению с x.operator+(y)
правильный, "зависит от". В частности, это зависит от того, как было определено operator+
. Если он был определен как функция-член, вам нужно использовать x.operator+(y)
. Если он был определен как глобальная функция, вам нужно использовать operator+(x,y)
.
Когда компилятор сталкивается с выражением z=x+y;
, ваш компилятор достаточно умен, чтобы искать соответствующую форму. Вы не должны ожидать того или другого. Вы должны использовать x+y
.