Ответ
В C++ есть два основных способа запретить наследование от класса.
1. Использование ключевого слова final (C++11 и новее)
Это самый простой и рекомендуемый современный способ. Ключевое слово final указывается после имени класса.
class Base final { // Класс помечен как final
// ... содержимое класса ...
};
class Derived : public Base { // Ошибка компиляции: cannot derive from 'final' base
};
2. Использование приватного конструктора и friend-класса (до C++11)
Этот метод работает в любом стандарте, но сложнее. Конструктор делается приватным, а для создания экземпляров используется статический метод или friend-класс.
class NonInheritable {
private:
NonInheritable() {} // Приватный конструктор
public:
// Фабричный метод для создания экземпляров
static NonInheritable createInstance() {
return NonInheritable();
}
};
class Derived : public NonInheritable { // Ошибка: 'NonInheritable::NonInheritable()' is private
};
int main() {
auto obj = NonInheritable::createInstance(); // OK
// NonInheritable obj2; // Ошибка: конструктор приватный
}
Вывод: Для новых проектов используйте final. Старый метод с приватным конструктором полезен для поддержки legacy-кода или создания паттерна типа Singleton.
Ответ 18+ 🔞
А, ну это классика, ёпта! Ситуация, когда ты написал класс, а потом какой-нибудь распиздяй решает от него унаследоваться и всё поломать. Волнение ебать! Хочется взять и впендюрить ему в голову, что не всё в этом мире нужно плодить и размножать. К счастью, в C++ есть пара способов поставить на этом деле жирный крест.
1. Волшебное слово final (C++11 и новее)
Это как надеть на класс противозачаточный колпак, ёбааать. Просто, элегантно, и никаких неожиданных наследников. Пишешь final после имени класса — и всё, приехали. Компилятор сам всех разгонит.
class Base final { // Всё, приплыли. Этот класс — тупиковая ветвь эволюции.
// ... что там у тебя внутри ...
};
class Derived : public Base { // Ошибка компиляции! Нельзя наследоваться от 'final' класса.
// Чувак, тебе только что сказали "иди на хуй" на уровне языка.
};
2. Старый дедовский способ с приватным конструктором (для тех, кто живёт как будто в 2002-м)
Это для мазохистов или для ситуаций, когда твой компилятор древнее мамонта. Суть в том, чтобы спрятать конструктор так далеко, что до него никто не доберётся. Наследник не сможет его вызвать — и накрылся медным тазом вся идея наследования. Правда, и самому классу создавать себя становится проблематично, приходится выкручиваться через статические методы или friend-классы. Пизда рулю удобству, но работает.
class NonInheritable {
private:
NonInheritable() {} // Конструктор спрятан. Хуй с горы тебе, наследничек.
public:
// Приходится городить огород, чтобы хоть как-то себя создать.
static NonInheritable createInstance() {
return NonInheritable(); // А тут можно, мы же внутри класса.
}
};
class Derived : public NonInheritable { // Ошибка! Конструктор базы приватный, ты его не вызовешь.
// Сам от себя охуел, да?
};
int main() {
auto obj = NonInheritable::createInstance(); // Ок, создали через фабрику.
// NonInheritable obj2; // А вот так уже низя, конструктор-то приватный. Подозрение ебать чувствую к такому коду.
}
Итог, чувак: Если у тебя не каменный век, жми final и не парься. Это ядрёно удобно и понятно всем. Старый метод с приватным конструктором — это такой музейный экспонат, на который можно посмотреть, вспомнить, как страдали предки, и поблагодарить стандарт C++11 за то, что избавил нас от этого геморроя.