Перегрузка нескольких операторов 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 с любой стороны с минимальными накладными расходами кода.