• До сих пор нам казалось, что

Скачать презентацию • До сих пор нам казалось, что Скачать презентацию • До сих пор нам казалось, что

L13_1 Функции вывода, функции объекты.ppt

  • Количество слайдов: 11

> • До сих пор нам казалось, что объект cout и оператор « волшебным • До сих пор нам казалось, что объект cout и оператор « волшебным образом знают, как выводить на экран объекты разных типов. Но дело, конечно, не в волшебстве, а в том, что все эти объекты (строки, переменные int и double) стандартны, стоит попытаться вывести на экран объект класса complex, о котором оператору « ничего не известно, и компилятор сообщит: 'operator <<' not implemented in type 'ostream' for arguments of type 'complex' in function Main() (в классе ostream не определен оператор << для аргументов типа complex) • В этом сообщении есть важная информация. До сих пор мы не знали, к какому классу относится объект cout. Компилятор подсказывает нам: это класс ostream, и теперь у нас есть все необходимое, чтобы построить операторную функцию для вывода оператором « комплексных чисел.

> • Затруднение только в том, что этот оператор нельзя определить в созданном нами • Затруднение только в том, что этот оператор нельзя определить в созданном нами классе complex. Ведь собственные функции объекта (а операторные функции, определенные в классе, — такие же собственные) «пристегиваются» к самому объекту, а значит, вывод переменной должен быть в этом случае записан так: complex a; а << cout; • Но в C++ принята другая запись cout << а, что приводит к вызову одной из операторной функции (а именно cout. operator << () класса ostream. В этом классе не предусмотрено операторной функции для вывода переменных нашего класса complex, что и вызывает сообщение об ошибке. • Значит, вывод на экран стандартным для C++ способом (cout << a; ) можно организовать двояко: дописать в класс ostream операторную функцию для оператора вывода комплексных чисел, или же использовать внешнюю функцию с двумя параметрами: первым должна быть ссылка на объект cout, вторым — объект класса complex.

> • Дописывать класс ostream мы, конечно, не будем. А вот написать собственную операторную • Дописывать класс ostream мы, конечно, не будем. А вот написать собственную операторную функцию сможем. Если объявить ее дружественной классу complex, то выглядеть она будет так: class complex { friend ostream& operator << (ostream & stream, complex a); public: private: } ostream& operator << (ostream & stream, complex a) { stream << a. re_ << ". ” << a. im_ << endl <

> • Если передать объект cout, а не ссылку него, то компилятор попытается создать • Если передать объект cout, а не ссылку него, то компилятор попытается создать внутри операторной функции копию cout. Но нам нужен сам объект, ведь cout, как и экран монитора, у нас один. (Кстати, создать копию не получится, потому что в классе ostream нет конструктора копирования. ) • Если конструктор копирования объекта (complex a) выполняется медленно, лучше передать ссылку. Но объект класса comlex «маленький» и его можно передавать по значению.

> • Возвращает наша операторная функция ссылку на объект класса ostream — с тем, • Возвращает наша операторная функция ссылку на объект класса ostream — с тем, чтобы обеспечить вывод объектов по цепочке. Представим, что на экран выводится несколько объектов: cout << А << В << С; • Если учесть, что оператор независимо от переопределений всегда выполняется слева направо, то сначала выполнится часть cout << А. Если объект А известен классу ostream, вызывается операторная функция cout. operator << (A), которая возвращает ссылку, то есть другое имя объекта cout. Так что можно сказать, что после вывода А цепочка укоротится: cout << В << С; • Если объект В не известен классу ostream (потому, например, что это объект созданного нами типа complex), то вызывается внешняя операторная функция, такая как в предыдущем примере Но поскольку она принимает и возвращает ссылку на ostream, порядок вывода не нарушится: в зависимости от типа объектов будут вызываться либо операторные функции класса ostream, либо внешние операторные функции И так будет до тех пор, пока не исчерпается список выводимых объектов.

>Функции - объекты • Оператор (), приспособленный нами для доступа к элементам матрицы (см. Функции - объекты • Оператор (), приспособленный нами для доступа к элементам матрицы (см. раздел «Доступ к массиву» ), можно использовать и по прямому назначению — для создания объекта, ведущего себя как функция. Такие объекты, часто называемые функторами, более универсальны и больше соответствуют духу объектно-ориентированного программирования, где абсолютно все стремится стать настоящим объектом с интерфейсом и скрытыми от посторонних глаз данными.

> • • • • Вывод строк на экран. #include <iostream> #include <vector> #include • • • • Вывод строк на экран. #include #include #include using namespace std; void output(const string &arg) { cout << arg << endl; } int main() { vector words; words. push_back("На"): words. push_back("златом"); words. push_back("крыльце"): words. push_back("сидели"); for_each(words. begin(), words. end(), output); }

> • • • В нем используется простейший алгоритм for_each(), требующий двух итераторов и • • • В нем используется простейший алгоритм for_each(), требующий двух итераторов и функции, определяющей, какие действия произвести с каждым объектом контейнера. В нашем случае функция output () принимает ссылку на строку и выводит соответствующий объект на экран. Но представим себе, что программа должна выводить элементы контейнера не только на экран, а куда укажут, например, в файл. Обычно для этого в функциях заводят еще один параметр — тип устройства вывода, но в нашей функции output () этого сделать нельзя, потому что алгоритм foreach () использует функции только с одним параметром. Значит, объект вывода нужно сделать элементом данных класса, а роль функции выполнит правильно определенный оператор ()

> • • • • Вывод строк с помощью объекта-функции #include <iostream> #include <fstream> • • • • Вывод строк с помощью объекта-функции #include #include #include #include using namespace std: class output { public; output (ostream &chosen_out) : out_(chosen_out){} void operator() (const string &arg){ out_ << arg << endl; } private: ostream &out_; };

words; words. push_back("Ha"); words." src="https://present5.com/presentation/3/29872510_336052679.pdf-img/29872510_336052679.pdf-10.jpg" alt="> • • • int main() { ofstream fo(“zzz"); vector words; words. push_back("Ha"); words." /> • • • int main() { ofstream fo(“zzz"); vector words; words. push_back("Ha"); words. push_back("златом"); words. push_back("крыльце"); words. push_back("сидели"); for_each(words. begin(), words. end(), output(cout)); for_each (words. begin(), words. end(), output (fo)); fo. close(); }

> • • • В классе output объект out_ класса ostream, куда нужно вывести • • • В классе output объект out_ класса ostream, куда нужно вывести элементы контейнера, задается конструктором: output (ostream &chosen_out) : out_(chosen_out){} а поведение функции обеспечивает оператор (). Теперь при выводе на экран объект класса output получает при создании имя объекта cout: for_each( output(cout)); , а при выводе в файл — объект класса ofstream: for_each( output(fo)); С классом ofstream мы до сих пор не встречались, потому что занимались только чтением готовых файлов — объектов класса ifstream. Класс ofstream отличается тем, что файлы, принадлежащие ему, можно заново создавать и потом записывать в них данные.