Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Билеты по ООП.doc
Скачиваний:
4
Добавлен:
14.04.2019
Размер:
596.48 Кб
Скачать

32. Чисто виртуальные функции и абстрактные типы

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

Чисто виртуальная функция является функцией, которая объявляется в базовом классе, но не имеет в нём определения. Поскольку она не имеет определения в базовом классе, то всякий производный класс обязан иметь свою собственную версию определения. Синтаксис:

virtual тип имя_функции(список_параметров) = 0;

Пример, следующая версия функции show_area() класса figure является чисто виртуальной функцией.

class figure {

protected:

double x, y;

public:

void set_dim(double i, double j=0) {

x = i;

y = j;

}

virtual void show_area() = 0;

};

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

Пример, если попытаться откомпилировать эту версию программы, то будет выдана ошибка:

#include <iostream>

using namespace std;

class figure {

protected:

double x, y;

public:

void set_dim(double i, double j=0) {

x = i;

y = j;

}

virtual void show_area() = 0;

};

class triangle: public figure {

public:

void show_area() {

cout << "Triangle with height ";

cout << x << " and base " << y;

cout << " has an area of ";

cout << x*0.5*y << ".\n";

}

};

class square: public figure {

public:

void show_area() {

cout << "Square with dimensions ";

cout << x << "x" << y;

cout << " has an area of ";

cout << x*y << ".\n";

}

};

class circle: public figure {

// определение show_area() отсутствует и поэтому

// выдаётся ошибка

};

int main()

{

figure *p;

triangle t;

square s;

p = &t;

p->set_dim(10.0, 5.0);

p->show_area();

p = &s;

p->set_dim(10.0, 5.0);

p->show_area();

return 0;

}

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

33. Раннее и позднее связывание

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

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

34. Классы потоков С++

С++ обеспечивает поддержку ввода-вывода в заголовочном файле iostream. Поскольку используются стандартные классы-шаблоны, необходима инструкция using namespace std. В файле iostream определены 2 иерархии классов, поддерживающие операции ввода-вывода. Класс нижнего уровня - streambuf. Этот класс обеспечивает базовые операции ввода-вывода. До тех пор пока не вводятся свои собственные классы ввода-вывода, непосредственно streambuf не используется. Вторая иерархия классов начинается с ios. Он обеспечивает поддержку форматированного ввода-вывода. От него порождены классы istream, ostream и iostream. Эти классы использованы для создания потоков, способных осуществлять ввод, вывод и ввод-вывод соответственно. От класса ios порождено много других классов, поддерживающих файлы на диске и форматирование в памяти.

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