Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП на языке С++.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
2 Мб
Скачать
☆

6.7. Определение пользовательских манипуляторов

В ситуации, когда нужно повторно определять одну и ту же команду форматирования, пользовательский манипулятор обеспечивает простую запись, нечто вроде макро.

Манипулятор без параметра создается следующим образом. Определяется класс с функцией operator<<(), которая, в свою очередь, вызывает определенные функции форматирования.

Пример 6.7.1.

Определим класс манипулятора

class my_f{};

Перегрузим функцию-оператор operator<< для объекта класса манипулятора. Манипулятор позволит выполнить выравнивание по правому краю. По умолчанию выравнивание по левому краю.

ostream& operator<<(ostream& out,my_f)

{

out.width(12);

out.fill(‘# ’);

cout.setf(ios:: right,ios::adjustfield);

return out;

}

void main()

{my_f MF;

cout<<52.3456<<endl<<MF<<52.3456<<endl;

}

Синтаксис языка разрешает параметры без имен, если последние не используются в теле функции. В стандарте языка С++ отмечается, что использование специального параметра без имени «полезно для резервирования места в списке параметров». В дальнейшем этот параметр может быть введен в функции без изменения интерфейса, т.е. без изменения вызывающей программы. Такая возможность бывает удобной при развитии уже существующей программы за счет изменения входящих в нее функций.

Так как манипулятор–это функция, принимающая и возвращающая ссылку на поток, то лучше определить манипулятор MF так:

Пример 6.7.2..

ostream& MF(ostream& out)

{

return out<<resetiosflags(ios::right)<<setiosflags(ios::right);

}

Эти два примера показывают два различных подхода к созданию пользовательских манипуляторов. В первом случае мы, по сути, не создавали манипулятор, а перегрузили операцию >> для класса my_f. Во втором случае мы создали собственно функцию-манипулятор. Вызов её обеспечивает перегруженная операция << в классе ostream.

6.8. Пользовательские манипуляторы с параметрами

Пусть, например, необходимо создать новый манипулятор с параметрами wp(n,m), где n – ширина поля вывода, m – точность.

Пример 6.8.1.

//Класс манипулятора

class my_manip {

int n,m;

ostream&(*f)(ostream&,int,int);

public:

//конструктор

my_manip(ostream&(*F)(ostream&,int,int),int N, int M): f(F),n(N),m(M){}

//здесь f,F – указатели на функцию

friend ostream& operator<<(ostream& s,my_manip& my)

{return my.f(s,my.n,my.m);}

};

ostream& wi_pre(ostream& s,int n,int m)

{s.width(n);

s.flags(ios::fixed);

s.precision(m);

return s;

}

my_manip wp(int n,int m)

{return my_manip(wi_pre,n,m);

}

void main()

{cout<<52.3456<<endl<<wp(10,5)<<52.3456<<endl;

}

Рассмотрим этот пример подробнее. Конструктор класса my_manip имеет первый аргумент ostream&(*F)(ostream&,int,int). Здесь F – указатель на функцию, имеющую три аргумента типов ostream&, int и int и возвращающую ссылку на класс ostream. Теперь конкретную функцию можно задавать для класса my_manip через указатель при конструировании объекта этого класса. Мы задали функцию wi_pre. При выполнении cout<<wp(10,5) фактически вызывается следующая функция:

osteram& operator<<(cout,wp(10,5))

{return wi_pre(cout,10,5);}

Действительно, функция wp возвращает объект класса my_manip с передачей в его конструктор параметров: wi_pre, n и m.

Сформулируем последовательность создания пользовательского манипулятора с параметрами.

1. Определить класс (my_manip) с полями: параметры манипулятора + поле – указатель на функцию типа

ostream& (*f)(ostream&,<параметры манипулятора>);

2. Определить конструктор этого класса (my_manip) с инициализацией полей.

3. Определить в этом классе дружественную функцию – operator<<. Эта функция в качестве правого аргумента принимает объект класса (my_manip), левого аргумента (операнда) поток ostream и возвращает поток ostream как результат выполнения функции f.

4. Определить функцию типа *f(wi_pre), принимающую поток и параметры манипулятора и возвращающую поток. Эта функция выполняет форматирование.

5. Определить собственно манипулятор (wp) как функцию, принимающую параметры манипулятора и возвращающую объект my_manip, поле f которого содержит указатель на функцию wi_pre.

При выполнении манипулятора cout<<wp(10,5); вызывается функция wp, которая создает и возвращает объект my_manip, в поле f которого содержится указатель на функцию wi_pre.

Затем вызывается функция operator<<, которой передается объект my_manip, созданный функцией wp.

Наконец, функция operator<< выполняет функцию *f, т.е. wi_pre, и возвращает поток.