Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 54, средняя оценка - 4.83
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
#1

Перегрузка operator<< - C++

17.02.2011, 00:10. Просмотров 6815. Ответов 40
Метки нет (Все метки)

Доброе время суток.

Есть очередная задачка - перегрузить оператор вывода таким образом:

Есть три объекта разных классов - А а, В в, С с;

Нужно, чтобы при записи а << b << c; изменялось значение некоторых членов всех трех классов, ну грубо говоря, пусть там есть по одному члену типа float и пусть при такой записи вывода произойдет нечто вроде
b.f+=0.2*c.f;
a.f+=0.8*c.f;

А при любой другой записи - (b<<c<<a, c<<b<<a, b<<a<<c, a<<b<<a) - пусть проводится просто вывод каких-нибудь членов класса, не суть важно. Или даже ошибка за неправильный порядок членов в выводе.

Можно ли это вообще сделать, а если нельзя, то что требуется от этих трех объектов?

Точно известно, что речь про перегрузку вывода, а не перегрузку сдвига.
С перегрузкой я знаком, но вызывает затруднение именно такой порядок и вообще, наличие 3х объектов, о которых идет речь.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
17.02.2011, 00:10
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Перегрузка operator<< (C++):

перегрузка operator<< - C++
помогите отгадать в чет ошибка class MCL{ private: int x,y; public: friend ostream&amp; operator&lt;&lt;(ostream &amp;s, MCL &amp;c); }; ...

Перегрузка operator[] - C++
Забыл как перегружать оператор для присваивания значений, а найти не могу ._. Чтобы было вот так: Class A { private: char...

Перегрузка operator= - C++
Возможно ли перегрузить оператор= так, что бы можно было написать? val = {10, 20, 15};

Перегрузка operator+ - C++
при сложени myVector2 = myVector0 + myVector1; выодит сообщения &quot;конструктоор 0&quot; ...1,...2,....2(копирования) а потом деструктор 2,2,1,2...

Перегрузка operator new - C++
Столькнулся с такой проблемой: Есть класс Array, в его конструкторе создается массив int Array::Array(const size_t...

Перегрузка operator= - C++
const Point&amp; operator= (const Point &amp;p) { if (this ==&amp;p) return *this; x = p.x; y = p.y; color = p.color; ...

40
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 19:22 #16
Цитата Сообщение от silent_1991 Посмотреть сообщение
Операторы сравнения действительно сравнивают
если определен operator==( .. ) то он может делать что угодно, кроме сравнение адресов объектов
Цитата Сообщение от silent_1991 Посмотреть сообщение
а оператор индексации действительно даёт доступ к нужному элементу
std::vector<T>::operator[] как связан с сишным a[x] <==> *(a+x) ?
C
1
2
std::map<char,int> map;
map['f'] = 100;
как связан с этим?
еще оператор = как конструктор копирования
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
17.02.2011, 19:30 #17
alex_x_x, ну вот, оказывается, мы о разных вещах говорим))) Вернее находимся на разных уровнях абстракции. Нам ведь важно то, что применив к экземпляру std::vector оператор [] мы получим необходимый элемент массива. Т.е. будет сымитировано поведение сырого массива. Нам же не обязательно знать, что для сырого сишного массива компилятор развернёт arr[i] в *(arr + i), а при применении вектора будет вызвана функция arr.operator[](i). Нам важно, что интерфейс совпадает, и мы вправе ожидать одинакового поведения. Вот об этом я и говорю.

Добавлено через 2 минуты
Нет, понятно, что мы можем перегрузить большинство операторов, как нам заблагорассудится, но я говорю о разумном использовании перегрузки. Например, конкатенация строк. Ведь интуитивно понятнее использовать для этого оператор сложения, чем отдельную функцию. Вот что я имею ввиду под разумным использованием))) То же и для <</>>. Тут просто интуитивно понятное действие.
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 19:38 #18
Цитата Сообщение от silent_1991 Посмотреть сообщение
Нам важно, что интерфейс совпадает, и мы вправе ожидать одинакового поведения. Вот об этом я и говорю.
я и не против
просто есть в программирование такое понятие как оператор и оно не связано с этими абстракциями
бинарный оператор
a * b
унарный
* a
и нет разницы
a << b
где a b два числа
или a - std::cout и b std::string
семантика одинакова, один оператор в разных контекстах приведет к разным действиям компилятора
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
17.02.2011, 19:42 #19
alex_x_x, да, а есть ещё ассемблер и машинный код, который вообще с регистрами да аккумуляторами работает (грубо). Так что нам уровень абстракции всё-таки важен. Верите, нет, но мне в контексте std::cout << str; легче оператор << называть оператором передачи в поток, чем оператором сдвига, и что язык ни о каком таком операторе вывода не знает, мне как-то по-барабану. Главное, что о нём знаю я, и смысл его мне понятнее, когда я его оператором вывода называю. Вот как-то так...

P.S. Главное знать, где, как и что правильно обозвать, чтобы потом не было мучительно больно за непонимание, какого чёрта "оператор вывода" делает в выражении a = b << 3;
Ну и плюс к этому, я бы и не заикался на эту тему, говори мы о Си, и не называл бы функцию printf оператором вывода.
0
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
17.02.2011, 19:44  [ТС] #20
Не, не сарказм, искреннее восхищение.

Просто не знал этой части и всегда считал сдвиг в операторах вывода некой идиомой плюсов.
0
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
18.02.2011, 21:58  [ТС] #21
Господа, получил небольшое облегчение задачи по теме.

Реализуйте класс, описывающий работу фильтра.
Перегрузите операции ввода-вывода так, чтобы при прохождении жидкости через фильтр (операция вида СОСУД << ФИЛЬТР << КОЛБА) в фильтре оставалось какое-то количество воды, заданное заранее в конструкторе в виде процента от исходного объема.

Сдается мне, что это похоже на токенайзер какой-то - разбор выражения типа...

Или может быть даже просто сделать перегрузку оператора ввода, а три больших слова - открытыми членами класса и выводить их. Ну и параллельно менять описываемый объем. Или это слишком просто?
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
18.02.2011, 22:02 #22
Так речь-то всё-таки идёт о перегрузке именно оператора <<, с выводом никак не связанной.
0
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
19.02.2011, 23:53  [ТС] #23
Но ведь написано "перегрузить операторы ввода-вывода"...
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
19.02.2011, 23:55 #24
Selendis, почитайте обсуждение на прошлой странице о <<
0
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
20.02.2011, 00:01  [ТС] #25
alex_x_x: А разве тут не идет речь о том, чтобы перегрузить <<, который уже был перегружен для basic_ios?(ну или где там cout определяются)

Плюс тут еще есть ввод, который наверное тоже куда-то в тему будет...
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
20.02.2011, 00:11 #26
Selendis, вы, похоже, не совсем понимаете суть перегрузки. Перегрузить оператор, который уже где-то перегружен, не получится. Везде, где оператор << не перегружен, он будет делать то, что должен делать согласно функциональности, определяемой ядром языка - сдвигать свой левый операнд на столько позиций влево, сколько указано во втором операнде. Вы либо используете его AsIs, либо перегружаете, давая ему новый функционал. То, что он уже где-то перегружен как оператор, отвечающий за вставку данных в поток, нам фиолетово. Мы, как и разработчики стандартного класса работы с потоками, просто перегружаем этот оператор языка так, чтобы он выполнял заданный функционал. По сути таким же образом, каким мы определяем оператор << для своего класса, передавая ему в качестве левого операнда экземпляр класса std::ostream, мы можем определить практически любой бинарный оператор, и радоваться, только потом, когда кто-то будет нашим классом пользоваться, нас проклянёт за такие выкрутасы.

Добавлено через 4 минуты
Вот пример того, как делать можно, но не нужно, чтобы вы убедились, что то, что оператор << называют оператором вывода в поток, определили разработчики стандартных классов работы с потоками. Определи они для этой цели другой оператор, кто знает, может данный код был бы вполне уместен)))

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
 
class Foo
{
public:
    Foo(int a = 0):
    _a(a)
    {
    }
 
    friend std::ostream &operator+(std::ostream &, const Foo &);
 
private:
    int _a;
};
 
std::ostream &operator+(std::ostream &output, const Foo &rhs)
{
    return output << rhs._a;
}
 
int main()
{
    Foo f1(1), f2(2), f3(3);
 
    std::cout + f1 + f2 + f3 << std::endl;
 
    return 0;
}
0
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
20.02.2011, 00:13  [ТС] #27
Ох, вроде бы немного понимал.

Выражусь вот так - прав ли я в том, что здесь требуется перегрузить не просто оператор <<, а скорее оператор <<, точно получающий левым операндом std::ostream?

Ведь грубо говоря, я могу ограничить понятие оператора вывода, определив его как сдвиг, получающий ostream в качестве левого операнда...

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

Или же я кругом не прав, и здесь правые и левые операнды уже указаны в задании, а для трех штук(СОСУД << ФИЛЬТР << КОЛБА) мне придется пользоваться его какой-нибудь ассоциативностью?
0
silent_1991
Эксперт С++
4993 / 3051 / 149
Регистрация: 11.11.2009
Сообщений: 7,038
Завершенные тесты: 1
20.02.2011, 00:18 #28
Полагаю, в задании ничего о выводе не сказано, а чётко сказано, что есть три объекта трёх классов, и их определённая последовательность в выражении a << b << c; задаёт определённое поведение программы. Вам же вроде на первой странице отписали несколько вариантов такой реализации, но вы почему-то ухватились за потоки и никак их не отпускаете, хотя в задании о них ничего не говорится.
0
Selendis
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
21.02.2011, 00:36  [ТС] #29
Ладно, не буду усложнять себе судьбу)
Уважаемый alex_x_x, а как в Вашем коде сделать так, чтобы грубо говоря
"a.value = c.value*b.value", причем только в случае "a<<b<<c" ?

Насколько я понял, там логично кейс для c будет позже кейса для a и обратиться к a уже никак нельзя. И в то же время, операция мне нужна только в случае a<<b<<c.

В голову лезут только вариант сделать глобальные экземпляры класса, вариант статических переменных и вариант сделать операцию явно опосля, достав какую-нибудь логическую переменную из менеджера.
0
alex_x_x
бжни
2450 / 1655 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
23.02.2011, 19:26 #30
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <cassert>
#include <string>
#include <iostream>
 
class Base{
public:
  int value;
  Base( int _value ) : value( _value ) {}
  virtual std::string getName() = 0;
};
 
#define CLASS(NAME)                  \
class NAME : public Base{            \
public:                              \
  NAME( int _value) : Base(_value){} \
  virtual std::string getName(){     \
    return #NAME;                    \
  }                                  \
};                               
 
 
#define BEGIN_SWITCH( COUNT )                \
do{                                          \
  switch( COUNT ) { 
 
#define CASE( NUM, TYPE, OBJ, GOOD, LP )     \
case NUM :                                   \
  if( !dynamic_cast<TYPE*>( OBJ ) ){         \
    GOOD = false;                  \
  }                                                    \
  LP[NUM] = OBJ;                             \
  break;
 
#define END_SWITCH()                         \
  default: assert( 0 );                      \
}} while(0)
 
CLASS(A);
CLASS(B);
CLASS(C);
 
Base& operator<<( Base& a, Base& b ){
  static unsigned uCount = 0;
  static bool bIsGood = true;
  static Base* lpB[3];
 
  std::cout << a.getName() << b.getName() << uCount << bIsGood << std::endl;
 
  BEGIN_SWITCH( uCount )
    CASE( 0, A, &a, bIsGood, lpB )
    CASE( 1, B, &a, bIsGood, lpB )
    CASE( 2, C, &a, bIsGood, lpB )
  END_SWITCH();
  if( 1 == uCount ){
    ++uCount;
    return b << b;
  }else if( 2 == uCount ){
    if( bIsGood ){
      //std::cout << "!\n";
      lpB[0]->value = lpB[1]->value * lpB[2]->value;
    }
    uCount = 0;
    bIsGood = true;
  }else{
    ++uCount;
  }
  return b;
}
 
int main(){
  A a(1);
  B b(2);
  C c(3);
  a << b << c;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
  b << b << c;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
  c << b << a;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
  a << b << c;
  std::cout << a.value << std::endl;  
  a.value = 0;
 
}
вот, насколько я понял

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[alexxx@localhost ~]$ g++ 6.cpp && ./a.out 
AB01
BC11
CC21
6
BB01
BC10
CC20
0
CB01
BA10
AA20
0
AB01
BC11
CC21
6
0
23.02.2011, 19:26
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
23.02.2011, 19:26
Привет! Вот еще темы с ответами:

Перегрузка operator-> () - C++
здравствуйте, объясните пож. как работает operator-&gt; (). Что происходит при этом мне понятно, но непонятно как. template &lt;typename T&gt; ...

Перегрузка operator+ - C++
Нужно сложить число с каждым елементом вектора, вот мой код: MyVectorClass.h namespace program { class MyVectorClass { ...

Перегрузка operator[][][] - C++
Здорова господа!!! Как перегрузить operator для класса или operator ??? Что нужно из него возвращать? От что то пытался но не...

Перегрузка operator->() - C++
Всем привет! Прохожу тему дескрипторов и меня удивляет как работает перегруженный operator-&gt;(). //какой то интерфейс struct...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
30
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.