- Основы ООП: абстракция
- Основы ООП: инкапусляция
- Основы ООП: наследование
- Основы ООП: полиморфизм
- Основы ООП: композиция (дизайн)
- Определение класса
- Права доступа
- Конструкторы: по умолчанию, параметрический, копирования
- Деструкторы
- Ссылка на себя: this
- Наследование
- Динамическое создание объектов: new и delete
- Указатели
- Виртуальные методы (virtual и override)
- Статические члены
- Вложенные типы, пространства имен и оператор контекста '::'
- Разнесение объявления и определения класса
- Абстрактные классы и интерфейсы
- Перегрузка операторов
- Приведение объектных типов: dynamic_cast и указатель void *
- Указатели, ссылки и const
- Управление наследованием: final и delete
Управление наследованием: final и delete
MQL5 позволяет накладывать некоторые ограничения на наследование классов и структур.
Ключевое слово final
С помощью ключевого слова final, добавленного после имени класса, разработчик может запретить наследование от этого класса. Например (FinalDelete.mq5):
class Base
|
Компилятор выдаст ошибку "нельзя наследоваться от 'Derived', потому что он определен как 'final'" ("cannot inherit from 'Derived' as it has been declared as 'final'").
Единого мнения по поводу пользы и сценариев использования такого ограничения, к сожалению, нет. Ключевое слово дает знать пользователям класса, что его автор по тем или иным соображениям не рекомендует брать его в качестве базового (например, его текущая реализация является черновой и будет сильно меняться, из-за чего потенциальные унаследованные проекты могут перестать компилироваться).
Некоторые пытаются таким образом стимулировать проектирование программ, в которых включение объектов (композиция) применяется вместо наследования. Чрезмерное увлечение наследованием действительно способно увеличить сцепление классов (т.е. взаимное влияние), поскольку все наследники тем или иным образом могут менять родительские данные или методы (в частности, переопределяя виртуальные функции). В результате возрастает сложность рабочей логики программы и вероятность непредвиденных побочных эффектов.
Дополнительным преимуществом от использования final может быть оптимизация кода компилятором: для указателей "финальных" типов он сможет заменить динамическую диспетчеризацию виртуальных функций на статическую.
Ключевое слово delete
Ключевое слово delete может быть указано в заголовке метода, чтобы сделать его недоступным в текущем классе и его наследниках. Виртуальные методы родительских классов удалять таким образом нельзя (это нарушило бы "контракт" класса, то есть наследники перестали бы "являться" ("is a") представителями того же рода).
class Base
|
Попытка его вызвать будет приводить к ошибке компиляции.
Мы видели похожую ошибку в разделе Приведение объектных типов, потому что компилятор обладает некоторым интеллектом, чтобы также "удалять" методы в определенных условиях.
Помечать удаленными рекомендуется следующие методы, для которых компилятор предоставляет неявные реализации:
- конструктор по умолчанию: Class(void) = delete;
- конструктор копирования: Class(const Class &object) = delete;
- оператор копирования/присваивания: void operator=(const Class &object) = delete.
Если вам требуется любой из них, следует его определить явным образом. В противном случае хорошим тоном считается отказаться от неявной реализации. Дело в том, что неявная реализация довольно прямолинейна и способна породить трудно локализуемые проблемы, в частности, при приведении объектных типов.