Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
2014_2015 / lect5_2_2015.pptx
Скачиваний:
11
Добавлен:
27.12.2015
Размер:
258.75 Кб
Скачать

Классы стандартных потоков ввода-вывода

Переопределение операций - ввести единую интерпретацию операций по отношению ко всем базовым типам данных и разрабатываемым классам, в т.ч. и стандартного ввода-вывода. библиотека iostream.h

class istream{…

istream &operator>>(int v){sсanf(“%d”,&v); return *this; } istream &operator>>(float v){scanf(“%f”,&v); return *this; } istream &operator>>(char c){ … }

istream &operator>>(char c[]){ … } void getline(char c[],int n){}

};

class ostream{…

ostream &operator<<(int v){ printf(“%d”,&v); return *this; } ostream &operator<<(float v){ printf(“%f”,&v); return *this; } ostream &operator<<(char c){ … }

ostream &operator<<(char c[]){ … } };

extern istream cin; extern ostream cout;

В классах istream и ostream переопределены операции >> и

<< для всех базовых типов данных и массивов сим-волов cin = __stdin_streambuf; // attach the standard files cout = __stdout_streambuf; //to the standard streams Это позволяет записывать выражения вида

cout << a << b << “AAAAAA”; cin >> a >> b; операндами в кот могут быть переменные и выражения базовых типов, а также массивы символов (строки).

Чтобы стандарт потоки ввода-вывода «понимали» объекты разрабатыв. классов - переопределить операцию вида ostream << newclass и istream >> newclass - только в виде дружеств операт в пользовательском классе newclass.

class newclass{…

friend operator ostream& <<(ostream &O, newclass &R) {… O << R.vv… return O; }

friend operator istream& <<(istream &O, newclass &R) {… O >> R.vv… return O; }}

Аналогично def классы файловых и строковых потоков fstream, ifstream, ofstream, istrstream, ostrstream + конструкторы и методы

Перегрузка функций

С++ позволяет определять в программе произвольное кол- во функций с одним именем при условии, что все они имеют разный состав параметров (разное количество или разные типы пара-метров). Состав параметров функции иногда называют ее сигнатурой. При вызове перегруженной функции в программе компилятор анализирует ее сигнатуру и выбирает из списка одноименных функций ту, сигнатура которой соответствует вызванной. Например, функции с прототипами

void Func(int); void Func(int,int); void Func(char*);

являются перегруженными; при вызове функции Func() с одним целочисленным аргументом будет вызвана первая функция, при вызове функции с тем же именем, но с двумя целочисленными ар-гументами – вторая, а при указании в качестве аргумента адреса символьной строки – третья. При этом возвращаемый функцией тип роли не играет.

Функции void Func(int); int Func(int);

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

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

Рассмотрим для примера вариант класса Men, объекты которого можно записывать на диск. В прежних вариантах этого класса имя человека хранилось в объекте в виде указателя на символы, т. е. в виде адреса строки с именем, которая сама располагалась где-то в другом месте памяти – нельзя хранить на диске в таком виде, потом прочитаете только адрес.

Для того чтобы объекты, в состав которых входят

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

class Men{

char name[20];//Будем надеяться, что этого хватит int age;

public:

Men(char* n, int a){ strcpy(name,n;) age=a;

} }; Создаются объекты такого класса обычным образом:

Men m1("Иванов",18);

Men* pm2=Men("Петров", 22);

Такие объекты можно будет хранить на диске (для этого в состав класса придется включить ф-ю, реализующую запись объекта в файл на диске), но при чтении данного с диска в памяти должно быть зарезервировано место, т.е. должны выделить в памяти место под объект

выделить в памяти место под объект создать «пустой»

объект этого класса Чтобы можно было создать такой «пустой» объект, в состав

класса следует ввести перегруженный конструктор без параметров (такой конструктор называют конструктором по умолчанию):

Men(){}

Такой конструктор ничего не делает, он только выделяет в па-мяти место под объект.

Варианты предложений создания «пустых» объектов будут иметь такой вид:

Men m1;

Men* pm2=new Men();

Основная сущность полиморфизма - в возможности

одновременно рассматривать один и тот же объект и как абстрактную сущность, на уровне которой он совместим с объектами других классов, и как сущность конкретную. Сам же механизм

полиморфных методов обеспечивает автоматическое

преобразование I представления во II во время работы программы.

Свойство полиморфности заключается в том, что при отсутствии полной информации о том, к какому из классов относится объект, функция (метод) в состоянии идентифицировать его класс и корректно выполниться в нем Этим самым создается иллюзия единой ф-ии в каждом из родственных классов – виртуальные ф-и.

Полиморфизм система родовых классов, в которой базовый класс порождает множество производных (непосредственно, либо путем цепочки наследований). В этой системе возможны переходы, связанные со сменой представлений.

При переходе от объекта производного класса к внут-

реннему объекту базового класса происходит абстра- гирование его сущности, а также потеря его конкрет-ных св-в - расширение. Обратный переход от объекта базового класса к объемлющему его объекту производ-ного - сужение и сопровождается конкретизацией его св-в.

В С (С++) ! способ смены интерпретации содержимого памяти (фактически преобразов. формы представления переменной или объекта при сохранении содержи-мого памяти) – преобразов. типа указателя (если рассматр несвязанные типы данных - машинно-ориентирован-ное – физич уровень представления данных в памяти)

Базовый и производный классы - доп. интерпретация - преобразуя указатель на объект производного класса к указателю на объект базового, получаем доступ к вложенному объекту базового класса – расширение, всегда корректно и поэтому может производиться без явного использования операции преобразования типа указателя - транслятор «забывает» об объекте произ- водного класса и вместо переопределенных в нем ме- тодов вызывает методы базового (остальные преоб- разования типов указателей должны быть явными)

class A {

f1(){}

 

public: void

 

};

 

 

 

class B : A {

f1(){}

// Переопределена в классe B

public: void

void

f2(){}

 

 

};

 

 

 

void main(){

 

 

B

x;

// Прямое преобр (расширение) - неявное

A *pa = &x;

pa->f1(); // Вызов A::f1(), хотя внутри объекта класса B

pb = (B*) pa;

// Обратное преобр (сужение) – явное

pb ->f2(); } // Корректно, если под pa был объект класса B После преобразования указателя на объект класса B в указатель на объект класса A происходит вызов ф-и из вложенного объекта базового класса A::f1(), хотя реально под указателем находится объект класса B.

Обратное преобразование от указателя на базовый класс к указателю на производный - только явно: будет корректно, если данный объект базового класса действительно содержится в объекте того производ-ного класса, к типу которого производится преобр указателя – иначе - динамич ошибка приведения типов - ошибка

времени выполнения, возникает или нет.

Внешний полиморфизм – ср-во объединения классов

Наличие общего базового класса - объединить в об-щую структуру данных объекты различной природы, приведя указатели на них к этому классу. Наличие в нем виртуальной ф-и - организовать регулярный про-цесс обработки данных, между которыми, в принципе, может и не быть ничего общего, кроме самого факта объединения и наличия общей ф-и обработки.

Наполнение общего базового класса может быть различным в зависимости от наличия у производных классов общего функционального наполнения:

· производные классы представляют собой вариации одной общей сущности, их общее функциональное наполнение может быть вынесено в базовый класс.

· производные классы не имеют никакой общей основы в виде данных и алгоритмов. Тогда виртуальные функции в базовом классе играют роль интерфейса (в терминах Java), позволяющего подключать объекты этого класса к общей системе обработки, требующей от них поддержки определенного обобщенного свойства.

Соседние файлы в папке 2014_2015