Можно ли каскадно перегружать оператор извлечения с перегруженными арифметическими операторами? - PullRequest
0 голосов
/ 05 февраля 2011

Я пытаюсь реализовать класс COMPLEX в C ++ и перегрузить арифметические операторы, а также операторы «<<» и «>>» для ввода / вывода. Индивидуально, а также в каскадном режиме арифметические операторы работают, как и ожидалось, - но я не могу получить правильные результаты при попытке выполнить операторы, такие как:

cout &lt&lt "something" &lt&lt complex1 + complex2 &lt&lt "\n";

где complex1 и complex2 - объекты класса COMPLEX.

фрагменты определения класса:

class COMPLEX{
    int a;  // Real part
    int b;  // Imaginary part
public:
    COMPLEX operator = (COMPLEX );
    COMPLEX operator + (COMPLEX ) const;
    friend istream& operator &gt&gt (istream &, COMPLEX &);
    friend ostream& operator &lt&lt (ostream &, COMPLEX &);
-snip-
}


COMPLEX COMPLEX::operator = (COMPLEX t_c) {
    return COMPLEX(a = t_c.a, b = t_c.b);
}

COMPLEX COMPLEX::operator + (COMPLEX t_c) const{
    return COMPLEX(a + t_c.a, b + t_c.b);
}

istream& operator &gt&gt (istream &i_s, COMPLEX &t_c){
    i_s &gt&gt t_c.a &gt&gt t_c.b;
    return i_s;
}

ostream& operator &lt&lt (ostream &o_s, COMPLEX &t_c){
    o_s &lt&lt t_c.a &lt&lt "+" &lt&lt t_c.b &lt&lt "i";
    return o_s;
}

кроме этого у меня также перегружен оператор.

Когда я пытаюсь каскадировать << с любым другим перегруженным оператором, перегруженная функция << friend не вызывается. Вместо этого вызывается оператор и отображается результат этого. </p>

Ответы [ 4 ]

1 голос
/ 05 февраля 2011

Ваш оператор << должен принимать постоянную ссылку, в противном случае компилятор не сможет преобразовать временный тип типа COMPLEX (который является результатом добавления) в неконстантную ссылку и может искать альтернативный оператор<< позвонить. </p>

friend ostream& operator << (ostream &, const COMPLEX &); //notice "const"

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

1 голос
/ 05 февраля 2011

Проблема в том, что ваш оператор вставки потока определен как

friend ostream& operator << (ostream &, COMPLEX &);

Принимает неконстантную ссылку на объект COMPLEX в качестве второго параметра. Когда вы пытаетесь написать

cout << a + b << endl;

Значение a + b представляет собой rvalue , а не lvalue , поскольку это значение, возвращаемое функцией operator +. В C ++ вы не можете привязать ссылку к r-значению, так как тогда вы могли бы делать плохие вещи следующим образом:

COMPLEX& c = a + b; // This step isn't legal
c = 137;            // Wait, what object did we just change?

Проблема здесь в том, что если мы можем связать ссылку c с временным объектом, возвращаемым a + b, то мы могли бы использовать ссылку для внесения изменений в этот объект. Но это не имеет никакого смысла - a + b - это значение выражения, а не фактического объекта.

Это та же проблема, что и здесь. Ваша operator << функция не может принимать a + b в качестве второго параметра, поскольку a + b является значением.

Чтобы исправить это, вы можете изменить operator << на const ссылку на КОМПЛЕКС:

friend ostream& operator<< (ostream& out, const COMPLEX& c);

Это работает, потому что в C ++ вы можете связывать константные ссылки с r-значениями. Это объясняется тем, что если у вас есть постоянная ссылка на временный объект, вы не можете вносить какие-либо изменения в этот временный объект, поэтому приведенный выше пример с привязкой ссылки к a + b больше не является проблемой.

Как правило, любой перегруженный оператор, принимающий параметр, тип которого является другим экземпляром класса, который не изменяет этот экземпляр, должен принимать свой параметр по константной ссылке. Это относится к таким вещам, как operator =, operator + и т. Д., Поскольку позволяет избежать этой проблемы.

0 голосов
/ 06 февраля 2011

Ваша проблема в том, что оператор << всегда вызывается перед оператором +. Тот факт, что вы предоставляете перегрузки, не меняет этого. </p>

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

0 голосов
/ 05 февраля 2011

переписать ваше cout заявление в

cout << "something" << (complex1 + complex2) << "\n";
...