Программирование. Принципы и практика использования C++ Исправленное издание, стр. 418
struct B { };struct B1: B { }; // B — открытый базовый класс по отношению // к классу B1struct B2: B { }; // B — открытый базовый класс по отношению // к классу B1struct C { };struct DD : B1, B2, private C { };DD* p = new DD;B1* pb1 = p; // OKB* pb = p; // ошибка: неоднозначность: B1::B или B2::BC* pc = p; // ошибка: DD::C — закрытый классАналогично, ссылку на производный класс можно неявно преобразовать в ссылку на однозначный и доступный базовый класс.
Более подробную информацию о производных классах можно найти в разделе 14.3. Описание защищенного наследования (
protectedA.12.4.1. Виртуальные функции
Виртуальная функция (virtual function) — это функция-член, определяющая интерфейс вызова функций, имеющих одинаковые имена и одинаковые типы аргументов в производных классах. При вызове виртуальной функции она должна быть определена хотя бы в одном из производных классов. В этом случае говорят, что производный класс замещает (override) виртуальную функцию-член базового класса.
class Shape {public: virtual void draw(); // "virtual" означает "может быть // замещена" virtual ~Shape() { } // виртуальный деструктор // ...};class Circle:public Shape { public: void draw(); // замещает функцию Shape::draw ~Circle(); // замещает функцию Shape::~Shape() // ...};По существу, виртуальные функции базового класса (в данном случае класса
ShapeCirclevoid f(Shape& s){ // ... s.draw();}void g(){ Circle c(Point(0,0), 4); f(c); // вызов функции draw из класса Circle}Обратите внимание на то, что функция
f()CircleShapeПодчеркнем, что класс, содержащий виртуальные функции, как правило, должен содержать виртуальный деструктор (как, например, класс
ShapeA.12.4.2. Абстрактные классы
Абстрактный класс (abstract class) — это класс, который можно использовать только в качестве базового класса. Объект абстрактного класса создать невозможно.
Shape s; // ошибка: класс Shape является абстрактнымclass Circle:public Shape {public: void draw(); // замещает override Shape::draw // ...};Circle c(p,20); // OK: класс Circle не является абстрактнымНаиболее распространенным способом создания абстрактного класса является определение как минимум одной чисто виртуальной функции (pure virtual function), т.е. функции, требующей замещения.
class Shape {public: virtual void draw() = 0; // =0 означает "чисто виртуальная" // ...};См. раздел 14.3.5.
Реже, но не менее эффективно абстрактные классы создаются путем объявления всех их конструкторов защищенными (
protectedA.12.4.3. Сгенерированные операции
При определении классов некоторые операции над их объектами будут определены по умолчанию.
• Конструктор по умолчанию.
• Копирующие операции (копирующее присваивание и копирующая инициализация).
• Деструктор.
Каждый из них (также по умолчанию) может рекурсивно применяться к каждому из своих базовых классов и членов. Создание производится снизу вверх, т.е. объект базового класса создается до создания членов производного класса. Члены производного класса и объекты базовых классов создаются в порядке их объявления и уничтожаются в обратном порядке. Таким образом, конструктор и деструктор всегда работают с точно определенными объектами базовых классов и членов производного класса. Рассмотрим пример.
struct D:B1, B2 { M1 m1; M2 m2;};Предполагая, что классы
B1B2M1M2void f(){ D d; // инициализация по умолчанию D d2 = d; // копирующая инициализация d = D(); // инициализация по умолчанию, // за которой следует копирующее присваивание