Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Абстрактные классы используются в качестве обобщенных концепций, на основе которых можно создавать более конкретные производные классы. Невозможно создать объект абстрактного типа класса. Однако можно использовать указатели и ссылки на абстрактные типы классов.
Вы создаете абстрактный класс, объявляя по крайней мере одну чистую виртуальную функцию-член. Это виртуальная функция, объявленная с помощью синтаксиса чистого описателя (= 0). Классы, производные от абстрактного класса, должны реализовывать чисто виртуальную функцию; в противном случае они также будут абстрактными.
Рассмотрим пример, представленный в функциях Virtual. Класс Account создан для того, чтобы предоставлять общие функции, но объекты типа Account имеют слишком общий характер для практического применения. Это означает Account , что это хороший кандидат для абстрактного класса:
// deriv_AbstractClasses.cpp
// compile with: /LD
class Account {
public:
Account( double d ); // Constructor.
virtual double GetBalance(); // Obtain balance.
virtual void PrintBalance() = 0; // Pure virtual function.
private:
double _balance;
};
Единственное различие между этим и предыдущим объявлениями состоит в том, что функция PrintBalance объявлена со спецификатором чисто виртуальной функции pure (= 0).
Ограничения на использование абстрактных классов
Абстрактные классы нельзя использовать для:
Переменные или данные-члены (нельзя объявить переменную типа абстрактного класса)
Типы аргументов (не удается передать абстрактный класс по значению в качестве параметра функции)
Типы возвращаемых функций (функция не может возвращать абстрактный класс по значению)
Типы явных преобразований (нельзя привести к типу абстрактного класса)
В каждом случае можно использовать указатели или ссылки на тип абстрактного класса. Например, функция может принимать AbstractBase& или AbstractBase* в качестве параметра, а также объявлять указатели или ссылки типа абстрактного класса.
Если конструктор абстрактного класса вызывает чистую виртуальную функцию напрямую или косвенно, результат не определен. Однако конструкторы и деструкторы абстрактных классов могут вызывать другие функции-члены.
Определенные чистые виртуальные функции
Чистые виртуальные функции в абстрактных классах можно определить или реализовать. Такие функции можно вызывать только с помощью полного синтаксиса:
abstract-class-name::function-name()
Определенные чистые виртуальные функции полезны при разработке иерархий классов, базовые классы которых включают чистые виртуальные деструкторы. Это связано с тем, что деструкторы базового класса всегда вызываются во время уничтожения объектов. Рассмотрим следующий пример:
// deriv_RestrictionsOnUsingAbstractClasses.cpp
// Declare an abstract base class with a pure virtual destructor.
// It's the simplest possible abstract class.
class base
{
public:
base() {}
// To define the virtual destructor outside the class:
virtual ~base() = 0;
// Microsoft-specific extension to define it inline:
// virtual ~base() = 0 {};
};
base::~base() {} // required if not using Microsoft extension
class derived : public base
{
public:
derived() {}
~derived() {}
};
int main()
{
derived aDerived; // destructor called when it goes out of scope
}
В примере показано, как расширение компилятора Майкрософт позволяет добавить встроенное определение в чистый виртуальный ~base(). Его можно также определить за пределами класса с помощью base::~base() {}.
Когда объект aDerived выходит из области, вызывается деструктор класса derived . Компилятор создает код для неявного вызова деструктора класса base после derived деструктора. Пустая реализация для чистой виртуальной функции ~base гарантирует, что для функции существует хотя бы какая-то реализация. Без него компоновщик создает неразрешенную ошибку внешнего символа для неявного вызова.
Примечание.
В предыдущем примере чистая виртуальная функция base::~base вызывается неявно из derived::~derived. Кроме того, можно явно вызывать чистые виртуальные функции с помощью полного имени функции-члена. Такие функции должны иметь реализацию, или вызов приводит к ошибке во время связи.