Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.70/44: Рейтинг темы: голосов - 44, средняя оценка - 4.70
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43

Перегрузка operator<<

17.02.2011, 00:10. Показов 9658. Ответов 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
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
17.02.2011, 00:10
Ответы с готовыми решениями:

Перегрузка operator>> и operator<< в абстрактном классе
Здрасьте! Есть необходимость перегрузить потоки, Я знаю как это сделать через friend, но вот кажется что есть и другое решение. Попытался...

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

Перегрузка operator<<
(Реализация дружественного оператора методом классов)При запуске программы неправильно работает дружественный оператор, не выводит...

40
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 00:15
https://www.cyberforum.ru/cpp-... print.html
friend функция С++ на MSVC 6.0
https://www.cyberforum.ru/cpp/thread162537.html

посмотрите, подобное уже решалось
0
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
17.02.2011, 08:56  [ТС]
Немного не то.

Я хочу не просто перегрузить оператор в трех классах, а сделать так, чтобы перегруженная операция выполнялась только в случае определенного порядка трех объектов разных классов:

Или даже так - для a<<b<<c выполняется одна версия cout, для любого другого a<<b, b<<a<<c, c<<b<<a - другая.
0
Эксперт С++
 Аватар для Хохол
476 / 444 / 34
Регистрация: 20.11.2009
Сообщений: 1,293
17.02.2011, 09:04
Невозможно это.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
17.02.2011, 13:50
Если раскомментировать какие-либо из закомментированных выражений, то выдает ошибку:
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/////////////////////////////////////////////////////////////////////////////////////////
//Есть очередная задачка - перегрузить оператор вывода таким образом:
//
//Есть три объекта разных классов - А а, В в, С с;
//
//Нужно, чтобы при записи а << 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х объектов, о которых идет речь. 
/////////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
/////////////////////////////////////////////////////////////////////////////////////////
typedef std::string  T_str;
/////////////////////////////////////////////////////////////////////////////////////////
class  T_base
{
    float  val_;
    //-----------------------------------------------------------------------------------
public:
    T_base(float  val) : val_(val)
    {}
    //-----------------------------------------------------------------------------------    
    void  set_zero()
    {
        val_ = 0;    
    }
    //-----------------------------------------------------------------------------------
    operator float()
    {
        return  val_;
    }
};
/////////////////////////////////////////////////////////////////////////////////////////
class  A : public T_base
{
public:
    A() : T_base(1)
    {}
};
/////////////////////////////////////////////////////////////////////////////////////////
class  B : public T_base
{
public:
    B() : T_base(2)
    {}
};
/////////////////////////////////////////////////////////////////////////////////////////
class  C : public T_base
{
public:
    C() : T_base(3)
    {}
};
/////////////////////////////////////////////////////////////////////////////////////////
class AB
{
    A&  a_;
    B&  b_;
    //-----------------------------------------------------------------------------------
public:
    AB(A&  a, B&  b) : a_(a), b_(b)
    {}
    //-----------------------------------------------------------------------------------
    AB(const AB&  ab) : a_(ab.a_), b_(ab.b_)
    {}
    //-----------------------------------------------------------------------------------
    void  operator<< (C&  c)
    {
        a_  .set_zero();
        b_  .set_zero();
        c   .set_zero();
    }
};
/////////////////////////////////////////////////////////////////////////////////////////
AB  operator<< (A&  a, B&  b)
{    
    return  AB(a, b);    
}
/////////////////////////////////////////////////////////////////////////////////////////
void  print
    (
        T_str  message,
        A      a,
        B      b,
        C      c
    )
{
    std::cout << message
              << std::endl
              << a
              << " "
              << b
              << " "
              << c
              << std::endl
              << std::endl;
}
/////////////////////////////////////////////////////////////////////////////////////////
int main()
{
    std::locale::global(std::locale(""));
    A  a;
    B  b;
    C  c;
 
    print("Исходные значения:", a, b, c);
      
    //Если раскомментировать какие-либо из нижерасположенных выражений, то выдает ошибку.
    //a << c << b;   
    //b << a << c;
    //b << c << a;
    //c << a << b;
    //c << b << a; 
 
    //a << b << a;
   
    a << b << c;
    print("После оператора a << b << c:", a, b, c);
}
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 14:47
Mr.X, ТСу вроде надо было перегрузить оператор передачи в поток (для которого первым операндом является экземпляр std::ostrem), а не просто оператор сдвига.
0
Эксперт С++
 Аватар для Mr.X
3225 / 1752 / 436
Регистрация: 03.05.2010
Сообщений: 3,867
17.02.2011, 15:15
Цитата Сообщение от silent_1991 Посмотреть сообщение
Mr.X, ТСу вроде надо было перегрузить оператор передачи в поток (для которого первым операндом является экземпляр std::ostrem), а не просто оператор сдвига.
У автора вот так написано:
Цитата Сообщение от Selendis Посмотреть сообщение
Нужно, чтобы при записи а << b << c; изменялось значение некоторых членов всех трех классов
Да и перегрузить можно только встроенный оператор, а оператор вывода «<<» - это перегрузка оператора сдвига.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 15:21
вот мой вариант

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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include <iostream>
#include <sstream>
#include <string>
 
using namespace std;
 
class Base{
public:
  virtual string toString() = 0;
};
 
class A : public Base{
public:
  string toString(){ return "a"; }
};
 
class B : public Base{
  string toString(){ return "b"; }
};
 
class C : public Base{
  string toString(){ return "c"; }
};
 
class Manager{
private:
  unsigned uCount;
  stringstream str;
  bool bIsGood;
public:
  Manager() : uCount(0), str( stringstream::in | stringstream::out ), 
                     bIsGood( true )
  {
  
  }
 
  void out( ostream& os, Base* b ){
    if( bIsGood ){
      switch( uCount ){
      case 0:
         if( !dynamic_cast<A*>( b ) ){
           bIsGood = false;
         } 
         break;
      case 1:
         if( !dynamic_cast<B*>( b ) ){
           bIsGood = false;
         } 
         break;
      case 2:
         if( !dynamic_cast<C*>( b ) ){
           bIsGood = false;
         } 
         break;     
      }
      if( bIsGood ){
         str << b->toString();
      }else{
         str.str("");
      }
    }
 
    if( 2 == uCount ){
      if( bIsGood ){
         os << str.str();
      }
      uCount = 0;
      bIsGood = true;
    }else{
      ++uCount;
    }
  }
};
 
Manager man;
 
#define MACRO( OS, OBJ ) \
  man.out( OS, &OBJ );   \
  return OS;
  
 
ostream& operator<<( ostream& os, A& obj ){
  MACRO( os, obj );
}
 
ostream& operator<<( ostream& os, B& obj ){
  MACRO( os, obj );
}
 
ostream& operator<<( ostream& os, C& obj ){
  MACRO( os, obj );
}
 
int main(){
  A a;
  B b;
  C c;
 
  cout << a << b << b << endl;
  cout << a << b << c << endl;
  cout << b << a << c << endl;
  cout << a << b << c << endl;
 
}
Bash
1
2
3
4
5
[alexxx@localhost ~]$ ./a.out 
 
abc
 
abc
Добавлено через 4 минуты
про изменение полей объектов, тут уже в каждом операторе отдельные действия
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 16:51
Mr.X,
Цитата Сообщение от Mr.X Посмотреть сообщение
У автора вот так написано:
А ещё у автора написано
Цитата Сообщение от Selendis Посмотреть сообщение
Точно известно, что речь про перегрузку вывода, а не перегрузку сдвига
Цитата Сообщение от Mr.X Посмотреть сообщение
Да и перегрузить можно только встроенный оператор, а оператор вывода «<<» - это перегрузка оператора сдвига.
Ну вы ведь меня поняли и просто придираетесь, правда? Ладно, для большей конкретики так:
"ТСу нужна была реализация перегрузки оператора сдвига влево для передачи своего правого операнда в поток, представляемый левым операндом, плюс выполнить некие дополнительные действия."
0
1 / 1 / 0
Регистрация: 15.02.2011
Сообщений: 43
17.02.2011, 18:15  [ТС]
silent_1991: Вы очень круты. Я и сам не знал, что мне нужно именно это!
Ведь правда - мне конечно нужна реализация оператора вывода. Однако реализация сдвига, которая будет выводить - это вообще супер.

Дальше уже понятно, как это доработать, спасибо.
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 18:32
Цитата Сообщение от Selendis Посмотреть сообщение
Вы очень круты
Никогда тугодумом не был, но немного не понял - это что, сарказм? Если нет - извиняюсь. А если так - то я основывался именно на вашей фразе
Цитата Сообщение от Selendis Посмотреть сообщение
Точно известно, что речь про перегрузку вывода, а не перегрузку сдвига.
Суть в том, что оператор << и есть оператор сдвига влево, просто для класса basic_ios (вроде для него, ну или для производных) он перегружен как оператор вывода в поток.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 18:54
оператора вывода просто не существует)
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 19:09
alex_x_x, ну ведь на нашем уровне абстракции мы имеем право "забыть", что в контексте ввода/вывода используются именно операторы сдвигов и для понятности называть их операторами ввода/вывода.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 19:14
silent_1991, так же как == != для объектов -> для умных указателей, [] для множеств итп
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 19:18
alex_x_x, не понял аналогии, все приведённые вами операции работают в соответствии с их назначением в, так сказать, реальной жизни. Операторы сравнения действительно сравнивают, а оператор индексации действительно даёт доступ к нужному элементу. А вот сдвиг работает не так, как надо, он не сдвигает, а выполняет иную функцию. Поэтому я и предлагаю чисто формально "забыть", что это именно оператор сдвига)))
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 19:22
Цитата Сообщение от 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
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 19:30
alex_x_x, ну вот, оказывается, мы о разных вещах говорим))) Вернее находимся на разных уровнях абстракции. Нам ведь важно то, что применив к экземпляру std::vector оператор [] мы получим необходимый элемент массива. Т.е. будет сымитировано поведение сырого массива. Нам же не обязательно знать, что для сырого сишного массива компилятор развернёт arr[i] в *(arr + i), а при применении вектора будет вызвана функция arr.operator[](i). Нам важно, что интерфейс совпадает, и мы вправе ожидать одинакового поведения. Вот об этом я и говорю.

Добавлено через 2 минуты
Нет, понятно, что мы можем перегрузить большинство операторов, как нам заблагорассудится, но я говорю о разумном использовании перегрузки. Например, конкатенация строк. Ведь интуитивно понятнее использовать для этого оператор сложения, чем отдельную функцию. Вот что я имею ввиду под разумным использованием))) То же и для <</>>. Тут просто интуитивно понятное действие.
0
бжни
 Аватар для alex_x_x
2473 / 1684 / 135
Регистрация: 14.05.2009
Сообщений: 7,162
17.02.2011, 19:38
Цитата Сообщение от silent_1991 Посмотреть сообщение
Нам важно, что интерфейс совпадает, и мы вправе ожидать одинакового поведения. Вот об этом я и говорю.
я и не против
просто есть в программирование такое понятие как оператор и оно не связано с этими абстракциями
бинарный оператор
a * b
унарный
* a
и нет разницы
a << b
где a b два числа
или a - std::cout и b std::string
семантика одинакова, один оператор в разных контекстах приведет к разным действиям компилятора
0
Эксперт С++
5058 / 3118 / 271
Регистрация: 11.11.2009
Сообщений: 7,044
17.02.2011, 19:42
alex_x_x, да, а есть ещё ассемблер и машинный код, который вообще с регистрами да аккумуляторами работает (грубо). Так что нам уровень абстракции всё-таки важен. Верите, нет, но мне в контексте std::cout << str; легче оператор << называть оператором передачи в поток, чем оператором сдвига, и что язык ни о каком таком операторе вывода не знает, мне как-то по-барабану. Главное, что о нём знаю я, и смысл его мне понятнее, когда я его оператором вывода называю. Вот как-то так...

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

Просто не знал этой части и всегда считал сдвиг в операторах вывода некой идиомой плюсов.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
17.02.2011, 19:44
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru