2013-03-21 2 views
1

Я создал класс сложных чисел, определенных операций и некоторых функций, таких как arg, модуль и т. Д. Я также определил мнимую единицу i как константу в пространстве имен. Проблема в том, что z = i + 2 не возвращает никаких ошибок и работает правильно, но компилятор не принимает строку z = 2 + i о том, что операнд недействителен между int и const complex.Операторы определены только одним способом - C++

Что мне делать, чтобы определить операцию в обоих направлениях?

+5

Хрустальный шар говорит мне, что вы попали в ловушку, чтобы сделать все функции своих операторов, когда они могут быть свободными функциями. – chris

ответ

3

Вы должны осуществлять либо преобразование между целым и комплексным числом или определяют как операторы:

complex operator+(int a, const complex& b) 

и

complex operator+(const complex& a, int b) 
+0

Когда я добавляю 1-ю функцию, у меня есть «перегруженный» оператор +, должен быть унарный или двоичный оператор (имеет 3 параметра) 'error – Moray

+0

@ user2145816, Поместите его за пределы класса. Каждый параметр нестационарной функции-члена является указателем на объект. – chris

+0

@ user2145816 поместите это за пределы вашего определения класса, иначе вы добавите неявный первый параметр 'this' типа complex. –

3

Вы должны перегружать complex operator+(int lhs, const complex& rhs); для вашего класса. Сделайте это функцией friend, чтобы передать оба параметра.

+5

Вам не нужны декларации 'friend', если вы определяете' + = 'и т. Д. Как функции-члены и используете их для реализации' + 'и т. Д. –

0

Существует два способа перегрузки операторов для классов: как функции-члены, так и ... ну, не-членные функции. Первые создаются, когда в этом случае есть объект класса (класс Complex) слева от оператора (+). Функции, не являющиеся членами, используются для тех случаев, когда это не происходит. Оба операнда указаны в этом случае, и сам перегруженный оператор случайно (иногда) создается внутри класса с доступом к другу (на самом деле он не нужен, если вы не будете обращаться к частным членам. класс состоит в том, что таким образом операторы данного класса находятся в одном и том же месте).

class Complex { 
public: 
    // more things... 

    Complex operator+(int i);        // cx + 1 
    friend Complex operator+(int i, const Complex &cx);  // 1 + cx 

    // more things... 
}; 

Complex Complex::operator+(int i) 
{ 
    Complex complexCopy(*this); 
    complexCopy.sum(i); 

    return complexCopy; 
} 

Complex operator+(int i, const Complex &cx) 
{ 
    Complex complexCopy(cx); 
    complexCopy.sum(i); 

    return complexCopy; 
} 

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

Надеюсь, что это поможет.

+0

Не-членские версии на самом деле не должны быть друзьями. – juanchopanza

+0

Уточненный, спасибо. – Baltasarq

2

В качестве альтернативы предоставлению реальных и сложных перегрузок для ваших операторов: Если вы дадите свой класс complex конструктор преобразования (конструктор, который не помечен explicit и может принимать один параметр), то он может неявно преобразовывать действительные числа для комплексных чисел:

class complex 
{ 
public: 
    complex(double real, double imag = 0) : real_(real), imag_(imag) {} 
    double real() const { return real_; } 
    double imag() const { return imag_; } 
private: 
    double real_; 
    double imag_; 
}; 

Затем вы можете определить operator+ как взятие двух complex параметров, и компилятор преобразует int в complex для вас:

complex operator+(const complex& a, const complex& b) 
{ 
    return complex(a.real() + b.real(), a.imag() + b.imag()); 
} 

Теперь, когда компилятор встречает этот код, он распознает, что complex, complex перегрузки operator+ существует и что 2 может быть неявно преобразован в complex:

z = 2 + i; 
0

Хороший способ справиться перегружать оператор + является начинаются с +=.

class complex { 
    double real 
    double imag; 
    complex& operator+=(complex const& other) { 
    real += other.real; 
    imag += other.imag; 
    return *this; 
    } 
    complex& operator+=(double other) { 
    real += other.real; 
    return *this; 
    } 
}; 

затем записать операторы, не являющиеся членами использовать выше оператора члена:

inline complex operator+(complex left, double right) { 
    return left+=right; 
} 
inline complex operator+(double left, complex right) { 
    return right+=left; 
} 
inline complex operator+(complex left, complex const& right) { 
    return left+=right; 
} 

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

Приятная вещь в этом плане заключается в том, что бинарные операторы являются реальным шаблоном, причем работа выполняется в операторе члена +=.

В C++ 11 вы можете сделать шаг дальше и автоматически записать все вышеперечисленные операторы, где он извлекает действительные типы на основе различных перегрузок operator+=. Но это стоит того, если вы пишете много классов, которые перегружают +.

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