2017-02-12 3 views
4

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

First Complex Number: 
Enter real part of complex number: 3 
Enter imaginary part of complex number: 6 

Second Complex Number: 
Enter real part of complex number: 5 
Enter imaginary part of complex number: -5 

a == (-27.00+36.00i) 
b == (5.00-5.00i) 
a+b == (-22.00+31.00i) 
a-b == (-32.00+41.00i) 
a*b == (45.00+315.00i) 
a*a == (-567.00-1944.00i) 
b*b == (0.00-50.00i) 
a*a (using postincrement) ==(-27.00+36.00i) 

Как вы можете видеть, не все с участием a это неправильно, потому что она занимает площадь a (комплексное число) как a. Итак, хотя ответ на вопрос «a*a (using postincrement) == (-27.00+36.00i) является правильным ответом ... в части, где указано« a == (-27.00+36.00i) », неверно, как и должно быть a==(3+6i). Я считаю, что ошибка кроется в перегрузках и аспектах моего кода, м. не знаю, как это исправить, как я не дал никаких ошибок ... это проблема логики в моем коде

Вот мой код:

#include<iostream> 
#include<iomanip> 
using namespace std; 

class ComplexNum 
{ 
public: 
    ComplexNum(float = 0.0, float = 0.0); //default constructor that uses default arg. in case no init. are in main 
    ComplexNum& getComplexNum(); //get real and imaginary numbers from keyboard 
    ComplexNum& sum(ComplexNum a, ComplexNum b); //method to add two ComplexNum numbers together 
    ComplexNum& diff(ComplexNum a, ComplexNum b); //method to find the difference of two complex numbers 
    ComplexNum& prod(ComplexNum a, ComplexNum b); //method to find the product of two complex numbers 
    ComplexNum& square(ComplexNum a); //method to find square using pre/post increment operators 

    //overloaded operators 
    ComplexNum& operator = (const ComplexNum& that) = default; 
    ComplexNum& operator += (const ComplexNum& that) { return sum(*this, that); } 
    ComplexNum& operator -= (const ComplexNum& that) { return diff(*this, that); } 
    ComplexNum& operator *= (const ComplexNum& that) { return prod(*this, that); } 
    ComplexNum& operator ++() { return square(*this); } //called for ++num 
    ComplexNum& operator ++(int) { return square(*this); } //called for num++ 

    ostream& print(ostream& stm = cout) const; 


private: 
    float real; //float data member for real number (to be entered in by user) 
    float imaginary; //float data member for imaginary number (to be entered in by user) 

    //non-member overloaded operators 
    //a is passed by value 
    friend ComplexNum operator+ (ComplexNum a, const ComplexNum& b) { return a += b; } 
    friend ComplexNum operator- (ComplexNum a, const ComplexNum& b) { return a -= b; } 
    friend ComplexNum operator* (ComplexNum a, const ComplexNum& b) { return a *= b; } 
    friend ComplexNum operator++(ComplexNum a) { return a++; } 

    friend ostream& operator<< (ostream& stm, const ComplexNum& c) { return c.print(stm); } 
}; 

ComplexNum::ComplexNum(float a, float b) 
{ 
    real = a; 
    imaginary = b; 
} 

ComplexNum& ComplexNum::getComplexNum() 
{ 
    ComplexNum keyboard; 
    cout << "Enter real part of complex number: "; 
    cin >> real; 

    cout << "Enter imaginary part of complex number: "; 
    cin >> imaginary; 

    return keyboard; 
} 

ComplexNum& ComplexNum::square(ComplexNum a) 
{ 
    this->real = (a.real * a.real) - (a.imaginary * a.imaginary); 
    this->imaginary = (2 * (a.real * a.imaginary)); 
    return *this; 
} 

ComplexNum& ComplexNum::sum(ComplexNum a, ComplexNum b) 
{ 
    this->real = a.real + b.real; 
    this->imaginary = a.imaginary + b.imaginary; 
    return *this; 
} 

ComplexNum& ComplexNum::diff(ComplexNum a, ComplexNum b) 
{ 
    this->real = a.real - b.real; 
    this->imaginary = a.imaginary - b.imaginary; 
    return *this; 
} 

ComplexNum& ComplexNum::prod(ComplexNum a, ComplexNum b) 
{ 
    this->real = (a.real * b.real) - (a.imaginary * b.imaginary); 
    this->imaginary = (a.real * b.imaginary) + (b.real * a.imaginary); 
    return *this; 
} 

ostream& ComplexNum::print(ostream& stm) const 
{ 
    return stm << "(" << noshowpos << real << showpos << imaginary << "i)"; 
} 

int main() 
{ 
    ComplexNum a, b; 
    cout << "First Complex Number:" << endl; 
    a.getComplexNum(); 
    cout << endl; 
    cout << "Second Complex Number:" << endl; 
    b.getComplexNum(); 
    cout << endl; 
    cout << fixed << setprecision(2) 
     << "a == " << a << '\n' 
     << "b == " << b << '\n' 
     << "a+b == " << a + b << '\n' 
     << "a-b == " << a - b << '\n' 
     << "a*b == " << a*b << '\n' 
     << "a*a == " << a*a << '\n' 
     << "b*b == " << b*b << '\n' 
     << "a*a (using postincrement) ==" << a++ << '\n'; 
     cout << endl; 

    system("PAUSE"); 
} 
+0

'ComplexNum & getComplexNum(); '- Где эта функция? – PaulMcKenzie

+0

Исследуйте термин «точки последовательности». Затем разделите свою длинную цепочку cout как минимум на 2 заявления. –

+1

Использование 'a ++' прерывает все другие применения 'a' в выводе. –

ответ

1

Это не про оператора перегрузка, это около order of evaluation.

В заявлении:

cout << fixed << setprecision(2) 
     << "a == " << a << '\n' 
     << "b == " << b << '\n' 
     << "a+b == " << a + b << '\n' 
     << "a-b == " << a - b << '\n' 
     << "a*b == " << a*b << '\n' 
     << "a*a == " << a*a << '\n' 
     << "b*b == " << b*b << '\n' 
     << "a*a (using postincrement) ==" << a++ << '\n'; 

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

Компилятор может вычислить значение каждого подвыражения в любом порядке, если значение «готово», когда оно необходимо распечатать. Таким образом, можно сделать что-то вроде этого:

auto&& temp1 = a + b; 
auto&& temp2 = a - b; 
auto&& temp3 = a*b; 
auto&& temp4 = a*a; 
auto&& temp5 = b*b; 
auto&& temp6 = a++; 
cout << fixed << setprecision(2) 
     << "a == " << a << '\n' 
     << "b == " << b << '\n' 
     << "a+b == " << temp1 << '\n' 
     << "a-b == " << temp2 << '\n' 
     << "a*b == " << temp3 << '\n' 
     << "a*a == " << temp4 << '\n' 
     << "b*b == " << temp5 << '\n' 
     << "a*a (using postincrement) ==" << temp6 << '\n'; 

Если это произошло, вы получите именно поведение вы ожидаете, потому что подвыражения будут оцениваться по порядку, слева направо. Но текущий C++-стандарт (C++ 14) позволяет компилятору переупорядочить оценки, что может позволить ему оптимизировать код лучше, если ему требуется меньше пространства стека с меньшим количеством регистров. Другое действительным выполнение инструкции будет:

auto&& temp1 = a++; 
auto&& temp2 = b*b; 
auto&& temp3 = a*a; 
auto&& temp4 = a*b; 
auto&& temp5 = a - b; 
auto&& temp6 = a + b; 
cout << fixed << setprecision(2) 
     << "a == " << a << '\n' 
     << "b == " << b << '\n' 
     << "a+b == " << temp6 << '\n' 
     << "a-b == " << temp5 << '\n' 
     << "a*b == " << temp4 << '\n' 
     << "a*a == " << temp3 << '\n' 
     << "b*b == " << temp2 << '\n' 
     << "a*a (using postincrement) ==" << temp1 << '\n'; 

На этот раз вы можете увидеть, что a++ операции происходит первую, и поэтому последующие расчеты будут сделаны после того, что случилось.

Компилятор также может выбрать любое другое упорядочение оценок подвыражений, например. он может оценить a*a затем ++a затем a-b и т.д. (но на практике наиболее часто встречающиеся заказы слева направо и справа налево)


Как в стороне, есть две другие серьезные проблемы с вашим код:

Эта функция возвращает ссылку на локальную переменную: не

ComplexNum& ComplexNum::getComplexNum() 
{ 
    ComplexNum keyboard; 
    // ... 
    return keyboard; 
} 

Это локальная переменная больше не существует после того, как функция возвращает, поэтому любая попытка использовать ссылку получает доступ к объекту, который не ExI ул. Никогда не делайте этого! Ваш компилятор должен был предупредить вас, что здесь возникла проблема, включить предупреждения своего компилятора и не игнорировать их!

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