2010-06-26 4 views
7

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

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*/ 

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

+0

Если вы заинтересованы в производительности, с точки зрения класса, возвращение '* this' через' const Myclass & 'будет лучше. Теперь, с точки зрения пользователя (если вы не компилируете на C++ 0x), вы должны использовать '+ =' вместо '+' и '=', чтобы избежать бесполезных времен, которые, возможно, не будут оптимизированы каким-то дерьмовым компиляторы. – paercebal

+0

Я понятия не имею, почему это было отклонено. Это совершенно правильный вопрос.(Тот факт, что вы найдете эту информацию в другом месте, не является основанием для того, чтобы здесь не найти ответ.) – sbi

+3

@paercebal: Он реализует сумму, а не прирост. Если бы он выполнял 'operator + =', то возврат ссылки был бы точным (после изменения внутреннего состояния), но 'a + b' не предназначен для изменения' a', а скорее производит третье значение, которое отличается от обоих 'a' и' b'. –

ответ

8

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

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

//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:: либо не требуется или даже не так..)

+1

+1 для правильной формы. Однако я бы, вероятно, использовал Boost.Operators для генерации бесплатных функций бесплатно. –

+0

Очень простой qn: Ваше определение для + требует, чтобы lhs был константой, тогда как код требует, чтобы вы написали lhs + = rhs. Кажется, вам либо нужно изменить свой код, либо ваше определение. Я прав? – vad

+0

@ Anon: Это был мой главный редактор. '' Я пошел и исправил его, и воспользовался возможностью, чтобы добавить мой стандартный отказ от ответственности. – sbi

9

Да.


Эти функции оператора являются только обычные функции со специальными именами [email protected]. Нет никаких ограничений, что они не могут быть перегружены. Фактически, оператор <<, используемый iostream, является оператором с несколькими перегрузками.

+0

Я чувствую себя плохо, засоряя ваш ответ комментарием. Пятно на. –

2

Да, вы можете перегружать таких операторов. Но я не уверен, что вы имеете в виду «switch case». Вы можете жить с одной перегрузкой, если у вас есть конвертирующий конструктор.

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) { 
    // ... 
} 

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

+0

Johannes, этот неявный конструктор преобразования может быть не очень хорошей идеей. Во-первых, IME-имплицитные конверсии обычно оказываются плохой идеей рано или поздно в любом случае, но также потому, что eladidan хочет это сделать, потому что «я создаю класс, который должен быть максимально оптимизирован». В этом случае перегрузки в любом случае лучше. – sbi

+1

О, и бездумно копировать 'inline blah MyClass ::' в 'MyClass' совсем не похоже на вас. ':)' – sbi

Смежные вопросы