Перегрузка нескольких операторов C++ для одного и того же оператора

Я знаю, что могу ответить на этот вопрос легко для себя, создав код и посмотреть, компилируется ли он. Но поскольку я не мог найти аналогичный вопрос, я подумал, что это знание стоит поделиться. Скажем, я перегружаю оператор + для MyClass. Могу ли я перегрузить его несколько раз. Различные перегрузки для разных типов. Вот так:

class MyClass{
...
inline const MyClass operator+(const MyClass &addend) const {
    cout<<"Adding MyClass+MyClass"<<endl;
    ...//Code for adding MyClass with MyClass
}
inline const MyClass operator+(const int &addend) const {
    cout<<"Adding MyClass+int"<<endl;
    ...//Code for adding MyClass with int
}
...
};
int main(){
    MyClass c1;
    MyClass c2;
    MyClass c3 = c1 + c2; 
    MyClass c4 = c1 + 5;
}
/*Output should be:
  Adding MyClass+MyClass
  Adding MyClass+in*/

причина, по которой я хочу это сделать, заключается в том, что я создаю класс, который я хочу максимально оптимизировать. Производительность-самая большая проблема для меня здесь. Поэтому литье и использование корпуса переключателя внутри функции operator + overloaded не является вариантом. Если вы заметите, я сделал обе перегрузки встроенными. Предположим на секунду, что компилятор действительно выравнивает мои перегрузки, тогда во время компиляции предопределяется, какой код будет выполняться, и я сохраняю вызов функции ( путем вставки) + сложный сценарий случая коммутатора (на самом деле будет 5+ перегрузок для оператора+), но я все еще могу писать легко читаемый код, используя basic арифметический оператор. Итак, получу ли я желаемое поведение?

3 ответов


каноническая форма реализации operator+() бесплатная функция на основе operator+=(), которые ваши пользователи будут ожидать, когда у вас есть +. += изменяет свой левый аргумент и, таким образом, должен быть членом. The + обрабатывает свои аргументы симметрично и, следовательно, должен быть свободной функцией.

что-то вроде этого должны сделать:

//Beware, brain-compiled code ahead!
class MyClass {
public:
    MyClass& operator+=(const MyClass &rhs) const
    {
      // code for adding MyClass to MyClass
      return *this;
    }
    MyClass& operator+=(int rhs) const
    {
      // code for adding int to MyClass
      return *this;
    }
};


inline MyClass operator+(MyClass lhs, const MyClass& rhs) {
  lhs += rhs;
  return lhs;
}
inline MyClass operator+(MyClass lhs, int rhs) {
  lhs += rhs;
  return lhs;
}
// maybe you need this one, too
inline MyClass operator+(int lhs, const MyClass& rhs) {
  return rhs + lhs; // addition should be commutative
}

(обратите внимание, что функции-члены, определенные с определением их класса неявно inline. Также обратите внимание, что в MyClass приставка MyClass:: либо не требуется, либо даже неправильно.)


да.


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


Да, вы можете перегрузить операторов, как это. Но я не уверен, о каком "переключателе" вы говорите. Вы можете жить с одной перегрузкой, если у вас есть конструктор преобразования

class MyClass{
...
// code for creating a MyClass out of an int
MyClass(int n) { ... }
...
inline const MyClass MyClass::operator+(const MyClass &addend) const {
    cout<<"Adding MyClass+MyClass"<<endl;
    ...//Code for adding MyClass with MyClass
}
...
};

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

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

inline const MyClass operator+(const MyClass &lhs, const MyClass &rhs) {
  // ...
}

Теперь, если вы сохраните конструктор преобразования, вы можете добавить int с любой стороны с минимальными накладными расходами кода.