Форум программистов, компьютерный форум CyberForum.ru

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

Войти
Регистрация
Восстановить пароль
 
 
dimcoder
Полярный
458 / 431 / 67
Регистрация: 11.09.2011
Сообщений: 1,129
#1

Не понимаю манипуляторы. Как они работают? - C++

08.02.2012, 11:51. Просмотров 947. Ответов 16

Здравствуйте. Столкнулся с непониманием манипуляторов. Вот код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
ostream& tab (ostream& output)          //Manipulator
{
    return output << "\t";
}
 
int main(int argc, char *argv[])
{
    cout << tab;
    cout << "Hello";       //How (?!?!) does it converts to: tab(cout), if it really does?
    //...................
    cout << endl;
    //...................
    tab(cout);             //I understand
    cout << "Hello ";
    system("PAUSE > NULL");
    return EXIT_SUCCESS;
}
Не понятно как cout << tab преобразуется в tab(cout).
Да и вообще не понятно, скажем как работает cout.precision(int)
Прошу объяснить, спасибо.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.02.2012, 11:51     Не понимаю манипуляторы. Как они работают?
Посмотрите здесь:
Find, replace Как они работают? C++
C++ Виртуальные функции, таблицы виртуальных методов, как они работают?
Постигаю c++ и не могу в здешние циклы, а ещё в тип char кто знает как они работают подскажите C++
C++ Что такое "bool " и #include <algorithm>? Кто знает , как они работают ?
Четыре комбайна работают с заданной производительностью, определить сколько они собрали зерновых C++
Манипуляторы. От С к С++ C++
C++ манипуляторы
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
08.02.2012, 11:57     Не понимаю манипуляторы. Как они работают? #2
C++
1
 cout.operator <<( tab );
Так понятнее?
dimcoder
Полярный
458 / 431 / 67
Регистрация: 11.09.2011
Сообщений: 1,129
08.02.2012, 12:09  [ТС]     Не понимаю манипуляторы. Как они работают? #3
Цитата Сообщение от villu Посмотреть сообщение
Так понятнее?
Не совсем. Пример конечно работает, но не понимаю почему. Ведь оно по моей идее должно преобразываться в
C++
1
operator<<(cout,tab);
Что получается, оператор << не перегружается здесь что ли?
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
08.02.2012, 12:23     Не понимаю манипуляторы. Как они работают? #4
dimcoder, для потоков вывода определён оператор <<, который принимает указатель на функцию. В теле он просто-напросто вызывает эту функцию и возвращает результат её выполнения.

Добавлено через 41 секунду
Цитата Сообщение от dimcoder Посмотреть сообщение
Ведь оно по моей идее должно преобразываться в
Нет, оно рассматривается компилятором так, как указал villu.
dimcoder
Полярный
458 / 431 / 67
Регистрация: 11.09.2011
Сообщений: 1,129
08.02.2012, 12:32  [ТС]     Не понимаю манипуляторы. Как они работают? #5
Цитата Сообщение от silent_1991 Посмотреть сообщение
определён оператор <<
}{м, то есть прототип функции вызова функций для cout записан так:
C++
1
2
3
4
5
6
7
class basic_ostream
{
   public:
   //blablabla
   void operator<< ((ostream&) * (ostream&));
   void operator<< ((const ostream &) *(ostream&))
}
Или как он/они все точно выглядит? Где их точно можно посмотреть?
villu
202 / 202 / 4
Регистрация: 06.08.2011
Сообщений: 600
Записей в блоге: 1
08.02.2012, 12:36     Не понимаю манипуляторы. Как они работают? #6
который принимает указатель на функцию.
Именно. Причем функцию, которая принимает
ostream& и возвращает ostream&

Для интереса попробуй сделать в том же коде

C++
1
wcout << tab; //
а после измени функцию так
C++
1
2
3
ostream& tab ( ostream& output, int t = 10 ) { ... }
....
cout << tab;
В этих случаях будет вызван другой вариант вызова operator << (). Скорее всего, с (void *) (может зависеть от реализации STL)

Добавлено через 2 минуты
Цитата Сообщение от dimcoder Посмотреть сообщение
Где их точно можно посмотреть?
в файле ostream пользуемой библиотеки. в студии, например тут c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\ostream
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
08.02.2012, 12:42     Не понимаю манипуляторы. Как они работают? #7
dimcoder, реализация gcc:
C++
1
2
3
4
5
6
7
8
      __ostream_type&
      operator<<(__ostream_type& (*__pf)(__ostream_type&))
      {
    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // DR 60. What is a formatted input function?
    // The inserters for manipulators are *not* formatted output functions.
    return __pf(*this);
      }
Добавлено через 4 минуты
Цитата Сообщение от villu Посмотреть сообщение
Причем функцию, которая принимает
ostream& и возвращает ostream&
Это я как-то само собой подразумевал, иначе ответом на вопрос это не являлось бы.
dimcoder
Полярный
458 / 431 / 67
Регистрация: 11.09.2011
Сообщений: 1,129
08.02.2012, 12:52  [ТС]     Не понимаю манипуляторы. Как они работают? #8
silent_1991,
villu, спасибо за ответы, но пока остались вопросы.

Цитата Сообщение от silent_1991 Посмотреть сообщение
Причем функцию, которая принимает
ostream& и возвращает ostream&
А если я не хочу каскадной записи? Вот допустим так:
http://liveworkspace.org/code/1d9a7f...758ebb26138fdd

Откуда здесь 1?

И как работает функция setw(int) из iomanip? Как создать такой манипулятор?
C++
1
cout << setw(6) << 289;

Цитата Сообщение от villu Посмотреть сообщение
В этих случаях будет вызван другой вариант вызова operator << (). Скорее всего, с (void *) (может зависеть от реализации STL)
У меня ошибку пишет.
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
08.02.2012, 13:00     Не понимаю манипуляторы. Как они работают? #9
dimcoder, тут тоже, скорее всего, вызывается версия с void *, потому что ваш "манипулятор" не соответствует сигнатуре функции, указатель на которую принимает остримовский оператор <<, т.е. манипулятора здесь не получается.

Цитата Сообщение от dimcoder Посмотреть сообщение
setw(int)
Тут уже другая схема, тут всё завязано на классах. Вот пример манипулятора, который выводит переданное ему число табуляций:

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
#include <iostream>
 
class tab
{
public:
    tab(size_t count):
    m_count(count)
    {
    }
 
    friend std::ostream& operator<<(std::ostream& stream, const tab& tab_manip)
    {
        for (size_t i = 0; i < tab_manip.m_count; ++i)
            stream << '\t';
 
        return stream;
    }
 
private:
    size_t m_count;
};
 
int main()
{
    std::cout << tab(3) << "Hello" << std::endl;
 
    return 0;
}
http://liveworkspace.org/code/45fd87...d17d153abe3179

Добавлено через 2 минуты
dimcoder, вот так, если сильно не хочется каскадной записи:
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
#include <iostream>
 
class tab
{
public:
    tab(size_t count):
    m_count(count)
    {
    }
 
    friend /*std::ostream&*/ void operator<<(std::ostream& stream, const tab& tab_manip)
    {
        for (size_t i = 0; i < tab_manip.m_count; ++i)
            stream << '\t';
 
        //return stream;
    }
 
private:
    size_t m_count;
};
 
int main()
{
    //std::cout << tab(3) << "Hello" << std::endl;
 
    std::cout << tab(3);
    std::cout << "Hello" << std::endl;
 
    return 0;
}
dimcoder
Полярный
458 / 431 / 67
Регистрация: 11.09.2011
Сообщений: 1,129
08.02.2012, 13:49  [ТС]     Не понимаю манипуляторы. Как они работают? #10
Спасибо большое за хороший пример. Вроде понял.
Остался вопрос, как реализован setprecision(int)
C++
1
2
3
#include <iomanip>
//...
cout << setprecision(3) << 3.234;
http://liveworkspace.org/code/27e6f5...e81da1cdbae12f

Я так понимаю класс содержащий setprecision является другом cout'a?

Или все таки можно описать класс чтобы можно было делать так:
C++
1
2
myClass multyplyByTen;
cout << multiplyByTen << 3;  //Ну типа умножили на десять и вывели
c выводом 30

Хотя врядли получиться, ведь приоритет слева направо и сначала вызовется cout.operator<< (multiplyByTen).
Я прав?
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
08.02.2012, 13:52     Не понимаю манипуляторы. Как они работают? #11
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
  struct _Setprecision { int _M_n; };
 
  /**
   *  @brief  Manipulator for @c precision.
   *  @param  n  The new precision.
   *
   *  Sent to a stream object, this manipulator calls @c precision(n) for
   *  that object.
  */
  inline _Setprecision 
  setprecision(int __n)
  { return { __n }; }
 
  template<typename _CharT, typename _Traits>
    inline basic_istream<_CharT, _Traits>& 
    operator>>(basic_istream<_CharT, _Traits>& __is, _Setprecision __f)
    { 
      __is.precision(__f._M_n); 
      return __is; 
    }
 
  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    operator<<(basic_ostream<_CharT, _Traits>& __os, _Setprecision __f)
    { 
      __os.precision(__f._M_n); 
      return __os; 
    }
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
08.02.2012, 14:11     Не понимаю манипуляторы. Как они работают? #12
Ой говнокод говнокодистый какой-то... Но работает.
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
#include <iostream>
 
class MultiplyByTenManip
{
public:
    MultiplyByTenManip(std::ostream *stream = 0):
    m_stream(stream)
    {
    }
 
    template<typename T>
    std::ostream& operator <<(const T& value)
    {
        return *m_stream << value * 10;
    }
 
    friend MultiplyByTenManip operator <<(std::ostream& stream, const MultiplyByTenManip& manip);
 
private:
    std::ostream *m_stream;
};
 
MultiplyByTenManip operator <<(std::ostream& stream, const MultiplyByTenManip&)
{
    return MultiplyByTenManip(&stream);
}
 
MultiplyByTenManip multiply_by_ten;
 
int main()
{
    std::cout << multiply_by_ten << 42 << std::endl;
 
    return 0;
}
http://liveworkspace.org/code/6b1e12...d89985b8645862

Главное - не пытаться ничего выводить прямо в multiply_by_ten, минуя поток... А то неприятно выводить что-то по нулевому адресу, считая его адресом потока
I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
08.02.2012, 14:18     Не понимаю манипуляторы. Как они работают? #13
А как сделать, чтобы на 10 умножались все последующие числа, а не только первое?
silent_1991
Эксперт С++
4960 / 3036 / 149
Регистрация: 11.11.2009
Сообщений: 7,027
Завершенные тесты: 1
08.02.2012, 14:31     Не понимаю манипуляторы. Как они работают? #14
I.M., а вот так вряд ли получится сделать, тут, скорее всего, действительно надо быть другом потока...
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.02.2012, 14:31     Не понимаю манипуляторы. Как они работают?
Еще ссылки по теме:
манипуляторы C++
Манипуляторы C++
C++ Манипуляторы в С++
Собственные манипуляторы C++
Залипающие манипуляторы C++

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

Или воспользуйтесь поиском по форуму:
dimcoder
Полярный
458 / 431 / 67
Регистрация: 11.09.2011
Сообщений: 1,129
08.02.2012, 14:31  [ТС]     Не понимаю манипуляторы. Как они работают? #15
Цитата Сообщение от silent_1991 Посмотреть сообщение
Ой говнокод говнокодистый какой-то...
Не, ну после вырезки из iomanip от forever - ваш код для меня - луч солнца в темном лесу.

Цитата Сообщение от I.M. Посмотреть сообщение
А как сделать, чтобы на 10 умножались все последующие числа, а не только первое?
Правда потом х выведешь что нибудь другое "каскадом"

http://liveworkspace.org/code/c57a2d...3c5dcf9a7c5073
Yandex
Объявления
08.02.2012, 14:31     Не понимаю манипуляторы. Как они работают?
Ответ Создать тему
Опции темы

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