// 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)
Здравствуйте, 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>не пойму в чём дело
Здравствуйте, 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<<.
А тот, котрый у тебя определен внутри класса работает в выражаниях типа
Здравствуйте, 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. Об этом тебе и сообщает компилятор.
Здравствуйте, 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
Здравствуйте, 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;
Операция вывода выглядит, как операция ввода — запись, совершенно сбивающая с толку! Согласитесь – это совсем не то, что мы хотели. Такая ситуация возникает потому, что «текущий» объект всегда является левым аргументом функций-методов.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!