Лекция
Привет, сегодня поговорим про абстрактные классы, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое абстрактные классы, чисто виртуальные методы , настоятельно рекомендую прочитать все из категории С++ (C plus plus).
Абстрактным называется класс, в котором есть хотя бы одна чистая (пустая) виртуальная функция.Чистой виртуальной называется компонентная функция, которая имеет следующее определение:virtual тип имя_функции(список_формальных_параметров) = 0;Чистая виртуальная функция ничего не делает и недоступна для вызовов. Ее назначение – служить основой для подменяющих ее функций в производных классах. Абстрактный класс может использоваться только в качестве базового для производных классов.Механизм абстрактных классов разработан для представления общих понятий, которые в дальнейшем предполагается конкретизировать. При этом построение иерархии классов выполняется по следующей схеме. Во главе иерархии стоит абстрактный базовый класс. Он используется для наследования интерфейса. Производные классы будут конкретизировать и реализовать этот интерфейс. В абстрактном классе объявлены чистые виртуальные функции, которые по сути есть абстрактные методы.
Пример 2.4.1
class Base{ public: Base(); // конструктор по умолчанию Base(const Base&); // конструктор копирования virtual ~Base(); // виртуальный деструктор virtual void Show()=0; // чистая виртуальная функция // другие чистые виртуальные функции protected: // защищенные члены класса private: // часто остается пустым, иначе будет мешать будущим разработкам };
class Derived: virtual public Base{ public: Derived(); // конструктор по умолчанию Derived(const Derived&); // конструктор копирования Derived(параметры); // конструктор с параметрами virtual ~Derived(); // виртуальный деструктор void Show(); // переопределенная виртуальная функция // другие переопределенные виртуальные функции Derived& operator=(const Derived&); // перегруженная операция присваивания // ее смысл будет понятен после прочтения главы 3 // другие перегруженные операции protected: // используется вместо private, если ожидается наследование private: // используется для деталей реализации };
По сравнению с обычными классами абстрактные классы пользуются “ограниченными правам”. Об этом говорит сайт https://intellect.icu . А именно:
Объект абстрактного класса не может быть формальным параметром функции, однако формальным параметром может быть указатель на абстрактный класс. В этом случае появляется возможность передавать в вызываемую функцию в качестве фактического параметра значение указателя на производный объект, заменяя им указатель на абстрактный базовый класс. Таким образом мы получаем полиморфные объекты.
Пример 2.4.2
Сформируем односвязный список, содержащий объекты разных классов, производных от одного абстрактного класса.
Когда виртуальная функция не переопределена в производном классе, то при вызове ее в объекте производного класса вызывается версия из базового класса. Однако во многих случаях невозможно ввести содержательное определение виртуальной функции в базовом классе. Например, при объявлении базового класса figure в предыдущем примере определение функции show_area() не несет никакого содержания. Она не вычисляет и не выводит на экран площадь объекта какого- либо типа. Имеется два способа действий в подобной ситуации. Первый, подобно предыдущему примеру, заключается в выводе какого-нибудь предупреждающего сообщения. Хотя такой подход полезен в некоторых ситуациях, он не является универсальным. Могут быть такие виртуальные функции, которые обязательно должны быть определены в производных классах, без чего эти производные классы не будут иметь никакого значения. Например, класс triangle бесполезен, если не определена функция show_агеа(). В таких случаях необходим метод, гарантирующий, что производные классы действительно определят все необходимые функции. Язык С++ предлагает в качестве решения этой проблемы чисто виртуальные функции.
Чисто виртуальная функция (pure virtual function) является функцией, которая объявляется в базовом классе, но не имеет в нем определения. Поскольку она не имеет определения, то есть
тела в этом базовом классе, то всякий производный класс обязан иметь свою собственную версию определения. Для объявления чисто виртуальной функции используется следующая общая форма:
virtual тип имя_функции(список параметров) = 0;
Здесь тип обозначает тип возвращаемого значения, а имя_функции является именем функции. Например, следующая версия функции show_area() класса figure является чисто виртуальной функцией.
class figure { double х, у; public: void set_dim(double i, double j=0) { x = i; y = j; } virtual void show_area() = 0; // чисто виртуальная };
При введении чисто виртуальной функции в производном классе обязательно необходимо определить свою собственную реализацию этой функции. Если класс не будет содержать определения этой функции, то компилятор выдаст ошибку. Например, если попытаться откомпилировать следующую модифицированную версию программы figure, в которой удалено определение функции
snow_area() из класса circle, то будет выдано сообщение об ошибке:
/* Данная программа не компилируется, поскольку класс circle не переопределил show_агеа() */ #include <iostream.h> class figure { protected: double x, y; public: void set_dim(double i, double j) { x = i; у = j; } virtual void show_area() = 0; // pure }; 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 * у << ". \ n"; } }; class square: public figure { public: void show_area() { cout << "Square with dimensions "; cout << x << "x" << y; cout << " has an area of "; cout << x * у << " . \n"; } }; class circle: public figure { // определение show_area() отсутствует и потому выдается ошибка }; int main ( ) { figure *р; // создание указателя базового типа circle с; // попытка создания объекта типа circle - ОШИБКА 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; }
Если какой-либо класс имеет хотя бы одну чисто виртуальную функцию, то такой класс называется абстрактным (abstract). Важной особенностью абстрактных классов является то, что не существует ни одного объекта данного класса. Вместо этого абстрактный класс служит в качестве базового для других производных классов. Причина, по которой абстрактный класс не может быть использован для объявления объекта, заключается в том, что одна или несколько его функций-членов не имеют определения. Тем не менее, даже если базовый класс является абстрактным, все равно можно объявлять указатели или ссылки на него, с помощью которых затем поддерживается полиморфизм времени исполнения.
В общем, мой друг ты одолел чтение этой статьи об абстрактные классы. Работы впереди у тебя будет много. Смело пиши комментарии, развивайся и счастье окажется в твоих руках. Надеюсь, что теперь ты понял что такое абстрактные классы, чисто виртуальные методы и для чего все это нужно, а если не понял, или есть замечания, то не стесняйся, пиши или спрашивай в комментариях, с удовольствием отвечу. Для того чтобы глубже понять настоятельно рекомендую изучить всю информацию из категории С++ (C plus plus)
Из статьи мы узнали кратко, но содержательно про абстрактные классы
Комментарии
Оставить комментарий
С++ (C plus plus)
Термины: С++ (C plus plus)