Перегрузка <<
От: enots  
Дата: 19.09.03 08:18
Оценка:
Вобщем решил потренироваться с перегрузкой




// modulus.cpp : Defines the entry point for the console application. 
// 

#include "stdafx.h" 
#include <stdio.h> 
#include <functional> 
#include <iostream> 

using namespace std ; 

class MathOps : public plus<int>, public minus<int>, 
                 public multiplies<int>, public divides<int>, 
                 public modulus<int> 
{ 
public: 
  int value; 
  MathOps(){value=0;} 
  MathOps(int x){value=x;} 
  result_type operator+(second_argument_type add2) 
                            {return value + add2;} 
  result_type operator-(second_argument_type sub2) 
                            {return value - sub2;} 
  result_type operator*(second_argument_type mult2) 
                            {return value * mult2;} 
  result_type operator/(second_argument_type div2) 
                            {return value / div2;} 
  result_type operator%(second_argument_type mod2) 
                            {return value % mod2;} 
  ostream& operator<<( ostream& os ) 
  { 
      os << this->value ; 
       return os ; 
  } 

}; 
/* 
ostream& operator<<(ostream& os, const MathOps& obj ) 
{ 
       os << obj.value ; 
       return os ; 
} 
*/ 
void main(void) 
{ 
  MathOps one,two,three,four,five,six; 

  cout << "Using MathOps class..." << endl ; 

  one = 18; 
  cout << "one = " << one << endl ; 
/* 
  two = one + 1; 
  cout << "two = one + 1 = " << two << endl ; 

  three = two - 2; 
  cout << "three = two - 2 = " << three << endl ; 

  four = three * 3; 
  cout << "four = three * 3 = " << four << endl ; 

  five = four / 4; 
  cout << "five = four / 4 = " << five << endl ; 

  six = five % 5; 
  cout << "six = five % 5 = " << six << endl ; 
  */ 
}


а компилятор выдаёт:
error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class MathOps' (or there is no acceptable conversion)

не пойму в чём дело
Re: Перегрузка <<
От: Павел Кузнецов  
Дата: 19.09.03 09:35
Оценка:
Здравствуйте, enots, Вы писали:

e>
e> class MathOps {
e> public:
e>   ostream& operator<<( ostream& os )
e>


(1) Операция с двумя операндами: левый — non-const MathOps, правый — ostream&.

e>
e> /*
e> ostream& operator<<(ostream& os, const MathOps& obj )
e> */
e>


(2) Уже лучше: левый — ostream&, правый — const MathOps&.

e>
e>   MathOps one;
e>   cout << "one = " << one << endl ;
e>


Первый вариант не подходит, т.к. ожидает операнды в обратном порядке.
Второй бы подошел, но он закоментирован.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re: Перегрузка <<
От: davenger  
Дата: 19.09.03 09:36
Оценка:
Здравствуйте, enots, Вы писали:

E>Вобщем решил потренироваться с перегрузкой




E>

E>// modulus.cpp : Defines the entry point for the console application. 
E>// 

E>#include "stdafx.h" 
E>#include <stdio.h> 
E>#include <functional> 
E>#include <iostream> 

E>using namespace std ; 

E>class MathOps : public plus<int>, public minus<int>, 
E>                 public multiplies<int>, public divides<int>, 
E>                 public modulus<int> 
E>{ 
E>public: 
E>  int value; 
E>  MathOps(){value=0;} 
E>  MathOps(int x){value=x;} 
E>  result_type operator+(second_argument_type add2) 
E>                            {return value + add2;} 
E>  result_type operator-(second_argument_type sub2) 
E>                            {return value - sub2;} 
E>  result_type operator*(second_argument_type mult2) 
E>                            {return value * mult2;} 
E>  result_type operator/(second_argument_type div2) 
E>                            {return value / div2;} 
E>  result_type operator%(second_argument_type mod2) 
E>                            {return value % mod2;} 

// Этот оператор позволяет сдвинуть ostream в MathOps (например one << cout;)
// а не наоборот, как ты хотел
E>  ostream& operator<<( ostream& os ) 
E>  { 
E>      os << this->value ; 
E>       return os ; 
E>  } 

E>}; 

// А вот этот делает то, что надо
E>/* 
E>ostream& operator<<(ostream& os, const MathOps& obj ) 
E>{ 
E>       os << obj.value ; 
E>       return os ; 
E>} 
E>*/ 
E>void main(void) 
E>{ 
E>  MathOps one,two,three,four,five,six; 

E>  cout << "Using MathOps class..." << endl ; 

E>  one = 18; 
E>  cout << "one = " << one << endl ; 
E>/* 
E>  two = one + 1; 
E>  cout << "two = one + 1 = " << two << endl ; 

E>  three = two - 2; 
E>  cout << "three = two - 2 = " << three << endl ; 

E>  four = three * 3; 
E>  cout << "four = three * 3 = " << four << endl ; 

E>  five = four / 4; 
E>  cout << "five = four / 4 = " << five << endl ; 

E>  six = five % 5; 
E>  cout << "six = five % 5 = " << six << endl ; 
E>  */ 
E>} 

 
E>


E>а компилятор выдаёт:

E>error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class MathOps' (or there is no acceptable conversion)

E>не пойму в чём дело
Re: Перегрузка <<
От: Vamp Россия  
Дата: 19.09.03 09:45
Оценка:
Здравствуйте, enots, Вы писали:

E>а компилятор выдаёт:

E>error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class MathOps' (or there is no acceptable conversion)
Все правильно. Ты же закомментировал внешний ostream& operator<<.
А тот, котрый у тебя определен внутри класса работает в выражаниях типа

one << cout;


Так что все правильно.
Да здравствует мыло душистое и веревка пушистая.
Re: Перегрузка <<
От: MaximE Великобритания  
Дата: 19.09.03 09:46
Оценка:
Здравствуйте, enots, Вы писали:

E>а компилятор выдаёт:

E>error C2679: binary '<<' : no operator defined which takes a right-hand operand of type 'class MathOps' (or there is no acceptable conversion)

operator<< для вывода в стандартный поток пользовательского класса должен перегружаться только как свободная функция, т.к. первым (левым) аргументом является поток. Ты же перегрузил его в качестве члена, т.е. он будет задействован только когда левым аргументом operator<< является твой класс, т.е. MathOps << ostream. Об этом тебе и сообщает компилятор.
Re[2]: Перегрузка <<
От: enots  
Дата: 19.09.03 09:54
Оценка:
Здравствуйте, Павел Кузнецов, Вы писали:


ПК>Первый вариант не подходит, т.к. ожидает операнды в обратном порядке.

ПК>Второй бы подошел, но он закоментирован.

да но вот если всё раскомментировать :

#include "stdafx.h"
#include <stdio.h>
#include <functional>
#include <iostream>

using namespace std ;
using namespace std ;

class MathOps : public plus<int>, public minus<int>,
                 public multiplies<int>, public divides<int>,
                 public modulus<int>
{
public:
  int value;
  MathOps(){value=0;}
  MathOps(int x){value=x;}
  result_type operator+(second_argument_type add2)
                            {return value + add2;}
  result_type operator-(second_argument_type sub2)
                            {return value - sub2;}
  result_type operator*(second_argument_type mult2)
                            {return value * mult2;}
  result_type operator/(second_argument_type div2)
                            {return value / div2;}
  result_type operator%(second_argument_type mod2)
                            {return value % mod2;}
  friend ostream& operator<<(ostream& os, const MathOps& obj ) ;
};

ostream& operator<<(ostream& os, const MathOps& obj )
{
       os << obj.value ;
       return os ;
}

void main(void)
{
  MathOps one,two,three,four,five,six;

  cout << "Using MathOps class..." << endl ;

  one = 18;
  cout << "one = " << one << endl ;

  two = one + 1;
  cout << "two = one + 1 = " << two << endl ;

  three = two - 2;
  cout << "three = two - 2 = " << three << endl ;

  four = three * 3;
  cout << "four = three * 3 = " << four << endl ;

  five = four / 4;
  cout << "five = four / 4 = " << five << endl ;

  six = five % 5;
  cout << "six = five % 5 = " << six << endl ;
}

то компилер выдаёт:

D:\Projects\modulus\modulus.cpp(46) : error C2593: 'operator <<' is ambiguous
D:\Projects\modulus\modulus.cpp(49) : error C2593: 'operator <<' is ambiguous
D:\Projects\modulus\modulus.cpp(52) : error C2593: 'operator <<' is ambiguous
D:\Projects\modulus\modulus.cpp(55) : error C2593: 'operator <<' is ambiguous
D:\Projects\modulus\modulus.cpp(58) : error C2593: 'operator <<' is ambiguous
D:\Projects\modulus\modulus.cpp(61) : error C2593: 'operator <<' is ambiguous
Error executing cl.exe.
Re[3]: Перегрузка <<
От: davenger  
Дата: 19.09.03 10:05
Оценка:
У меня VC6.0 не выдает никаких ерроров
Re[4]: Перегрузка <<
От: enots  
Дата: 19.09.03 10:14
Оценка:
Здравствуйте, davenger, Вы писали:

D>У меня VC6.0 не выдает никаких ерроров


А у меня как не крути выдаёт error, может что то подключить надо или ещё чего у кого нить идеи есть?
Re: Перегрузка <<
От: MaximE Великобритания  
Дата: 19.09.03 10:30
Оценка:
Здравствуйте, enots, Вы писали:

E>Вобщем решил потренироваться с перегрузкой


E>

[]

E>class MathOps : public plus<int>, public minus<int>, 
E>                 public multiplies<int>, public divides<int>, 
E>                 public modulus<int> 

[]
E>


А какой смысл в таком наследовании?
Re[2]: Перегрузка <<
От: enots  
Дата: 19.09.03 10:44
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, enots, Вы писали:


E>>Вобщем решил потренироваться с перегрузкой


E>>

ME>[]

E>>class MathOps : public plus<int>, public minus<int>, 
E>>                 public multiplies<int>, public divides<int>, 
E>>                 public modulus<int> 

ME>[]
E>>


ME>А какой смысл в таком наследовании?


Этот пример взят из MSDN, думаю смысл что бы в последствии использовать методы этих шаблонов
Re[3]: Перегрузка <<
От: MaximE Великобритания  
Дата: 19.09.03 11:09
Оценка:
Здравствуйте, enots, Вы писали:

E>Здравствуйте, MaximE, Вы писали:


ME>>Здравствуйте, enots, Вы писали:


E>>>Вобщем решил потренироваться с перегрузкой


E>>>

ME>>[]

E>>>class MathOps : public plus<int>, public minus<int>, 
E>>>                 public multiplies<int>, public divides<int>, 
E>>>                 public modulus<int> 

ME>>[]
E>>>


ME>>А какой смысл в таком наследовании?


E>Этот пример взят из MSDN, думаю смысл что бы в последствии использовать методы этих шаблонов


Очень сомнительна полезность такого наследования.

У этих шаблонов функция-член одна — operator(). Для того, чтобы пользователь MathOps мог использовать operator() он должен будет явно скастить
MathOps к одному из его базовых классов, иначе будет неоднозначность.

MathOps m;
m(m, 2); // ??? чей operator()? plus<int> или minus<int> или ... ?


Разработчик хотел именно этого?:

MathOps m;
static_cast<plus<int>&>(m)(m, 2); // === m + 2
Re: Перегрузка <<
От: LaptevVV Россия  
Дата: 22.09.03 06:12
Оценка:
Здравствуйте, enots, Вы писали:

E>Вобщем решил потренироваться с перегрузкой

skip весь текст

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

Попробуем теперь реализовать перегрузку «простой» операции сложения «внутренним» способом. Нам требуется операция, выполняющая сложение объекта типа Month с целым числом. Данная функция практически аналогична функции +=, но в данном случае требуется возвращать значение (листинг 4.38).
Листинг 4.38. «Внутренняя» реализация операции сложения
Month operator+(int b)
{ if (m!=empty_) return (monthName)((m+b)%12?(m+b)%12:dec_);
else return *this;
}
Однако при проверке данной операции
cout<<t+3<<endl; //--выводит «май»
cout<<3+t<<endl; //--выводит «5»
вдруг выясняется, что традиционная семантика нарушается: результат изменился от перемены мест слагаемых! Последний результат вызывает некоторое недоумение. Представим, однако, последние два вызова функции сложения в функциональной форме
cout<<t.operator+(3)<<endl;
cout<<3.operator+(t)<<endl;

Month — это огранниченный тип месяц года, от 1 до 12.

У внешней функции было два параметра: объект вывода и выводимый объект. У функции-метода, очевидно, должен быть один явный параметр – объект вывода, поскольку выводимый объект передается неявно. Таким образом, возможная реализация выглядит так:
ostream& operator<<(ostream& t)
{ return (t << '('<<num <<'/'<<denum<<')'); }
В определении ничего необычного не наблюдается. Однако напишем функциональный вызов такой функции для некоторого объекта R:
R.operator<<(cout);
В сокращенной записи получим
R<<cout;
Операция вывода выглядит, как операция ввода — запись, совершенно сбивающая с толку! Согласитесь – это совсем не то, что мы хотели. Такая ситуация возникает потому, что «текущий» объект всегда является левым аргументом функций-методов.

Хочешь быть счастливым — будь им!
Без булдырабыз!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.