Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

invalid initialization of non-const

#cpp #классы #ссылки #перегрузка_операторов


#include 
#include 

using namespace std;

class complex {
    double re, im;
public:
    complex(double = 0, double = 0);
    ~complex();

    complex operator+(complex&);
    complex operator-(complex&);
    complex operator*(complex&);
    complex operator/(complex&);
    complex operator^(unsigned);
    friend istream& operator >> (istream &, complex&);
    friend ostream& operator << (ostream &, complex &);
};

complex::complex(double r, double i)
{
    re = r;
    im = i;
}

complex::~complex() { }

complex complex::operator+(complex&y)
{
    return complex(re + y.re, im + y.im);
}

complex complex::operator-(complex&y)
{
    return complex(re - y.re, im - y.im);
}

complex complex::operator*(complex&y)
{
    return complex(re*y.re - im*y.im, re*y.im + im*y.re);
}

complex complex::operator/(complex&y)
{
    double r1 = re;
    double i1 = im;
    double r2 = y.re;
    double i2 = y.im;
    return complex((r1*r2 - i1*i1) / (r2*r2 + i2*i2), (-r1*i2 + i1*r2) / (r2*r2 +
i2*i2));
}

complex complex::operator^(unsigned n)
{
    complex y(1, 0);
        for (int i = 1; i <= n; i++)
            y = y*(*this);
    return y;
}

istream& operator >> (istream& is, complex& x)
{
    char c;
    cin >> c;
    assert(c == '(');
    cin >> x.re;
    cin >> c;
    assert(c == ',');
    cin >> x.im;
    cin >> c;
    assert(c == ')');
    return is;

}

ostream& operator<<(ostream&os, complex&x)
{
    os << '(' << x.re << ',' << x.im << ')' << endl;
    return os;
}

int main(){

    complex a(1, 1);
    complex b(1, 1);
    complex c(1, 1);
    complex x;

    cout << "Введите комплексное число в формате: (re,im) ->";
    cin >> x;
    cout << "Результат =" << a*(x ^ 2)) + b*x + c << endl;
    return 0;
}


На линуксе выводит ошибку:


  invalid initialization of non-const


для строки:

cout << "Результат =" << a*(x ^ 2) + b*x + c << endl;


Саму программу скопировал с Windows, ошибки исправил, только эту выдает. В чем здесь
проблема? И как можно ее решить? На Visual Studio работала нормально.
    


Ответы

Ответ 1



Объявите данные операторы следующим образом complex operator+( const complex&) const; complex operator-(const complex&) const; complex operator*(const complex&) const; complex operator/( const complex&) const; complex operator ^( unsigned int ) const; friend ostream& operator << (ostream &, const complex &); Нельзя связывать временные объекты с неконстантной lvalue ссылкой. Обратите внимание , что конструктор класса является преобразующим конструктором. Поэтому у вас будет работать выражение complex + double, как, например, complex a( 10, 10 ); complex b = a + 10; Но не будет работать выражение double + complex complex a( 10, 10 ); complex b = 10 + a; // ошибка компиляции так как ваши операторы являются членами класса. Вы могли бы их объявить как отдельные функции, не являющиеся членами класса, которые принимают два аргумента. Например, friend complex operator +( const complex &lhs, const complex &rhs ) { return complex( lhs.re + rhs.re, lhs.im + rhs.im ); } В этом случае второе выражение было бы также верным. Эта дружественная функция может быть определена как в самом классе, и тогда при использовании оператора будет применен зависящий от аргумента поиск (ADL), либо вне класса. Что касается Visual Studio, то его компилятор имеет собственные расширения языка (которые активизированы по умолчанию; вы можете отключить эту опцию в настройках компилятора, и тогда будет выдано сообщение об ошибке), которые порой противоречат стандарту C++. Не стоит полагаться на эти расширения языка компилятора C++ Visual Studio, так как код будет не переносимым. EDIT: Так как у вас возникают трудности правильно набрать код, то приведу для вас рабочий вариант программы. Я не проверял, определены ли правильно операторы с точки зрения математики. #include #include class complex { private: double re, im; public: complex( double = 0, double = 0 ); ~complex(); complex operator +( const complex & ) const; complex operator -( const complex & ) const; complex operator *( const complex & ) const; complex operator /( const complex & ) const; complex operator ^( unsigned int ) const; friend std::istream & operator >>( std::istream &, complex & ); friend std::ostream & operator <<( std::ostream &, const complex & ); }; complex::complex( double r, double i ) : re( r ), im( i ) { } complex::~complex() { } complex complex::operator +( const complex &c ) const { return complex( re + c.re, im + c.im ); } complex complex::operator -( const complex &c ) const { return complex( re - c.re, im - c.im ); } complex complex::operator *( const complex &c ) const { return complex( re * c.re - im * c.im, re * c.im + im * c.re ); } complex complex::operator /( const complex & c ) const { double r1 = re; double i1 = im; double r2 = c.re; double i2 = c.im; return complex( ( r1 * r2 - i1 * i1 ) / ( r2 * r2 + i2 * i2 ), (-r1 * i2 + i1 * r2 ) / ( r2 * r2 + i2 * i2 ) ); } complex complex::operator ^( unsigned int n ) const { complex c( 1, 0 ); for ( unsigned int i = 1; i <= n; i++ ) c = c * *this; return c; } std::istream & operator >>( std::istream &is, complex &c ) { char ch; is >> ch; assert( ch == '(' ); is >> c.re; is >> ch; assert( ch == ',' ); is >> c.im; is >> ch; assert( ch == ')' ); return is; } std::ostream & operator <<( std::ostream &os, const complex &c ) { return os << '(' << c.re << ',' << c.im << ')'; } int main() { complex a(1, 1); complex b(1, 1); complex c(1, 1); complex x; std::cout << "Введите комплексное число в формате: (re,im) ->"; std::cin >> x; std::cout << "x = " << x << std::endl; std::cout << "x ^ 2 = " << ( x ^ 2 ) << std::endl; std::cout << "a * ( x ^ 2 ) = " << a * ( x ^ 2 ) << std::endl; std::cout << "b * x = " << b * x << std::endl; std::cout << "a * ( x ^ 2 ) + b * x = " << a * ( x ^ 2 ) + b * x << std::endl; std::cout << "Результат =" << a * ( x ^ 2 ) + b * x + c << std::endl; return 0; } Если ввести значение (10,10), то вывод будет выглядеть следующим образом: Введите комплексное число в формате: (re,im) ->(10,10) x = (10,10) x ^ 2 = (0,200) a * ( x ^ 2 ) = (-200,200) b * x = (0,20) a * ( x ^ 2 ) + b * x = (-200,220) Результат =(-199,221)

Ответ 2



Для таких простых классов с семантикой значения и малым размером лучше делать операторы свободными функциями (в силу семантики), и даже, возможно, с передачей по значению (в силу малости - 2 double скопировать против разыменований адресов (ссылка работает через адрес) - неизвестно, что выиграет... Как минимум, стоит выполнить несколько хронометражей): friend complex operator+(complex a, complex b) { return complex(a.re+b.re,a.im+b.im); } Update Провел хронометраж. VC++ 2015. На 32 разрядах константная ссылка быстрее примерно в 1.5 раза. На 64 разрядах одинаково. В принципе, более-менее понятно, почему. Ну, значит, нужно friend complex operator+(const complex& a, const complex& b) { return complex(a.re+b.re,a.im+b.im); }

Комментариев нет:

Отправить комментарий