Приведите пример интерфейса из жизни
Что проверяют
Умеете ли вы объяснять абстракцию словами и знаете ли, чем интерфейс выражается в C++, где отдельного ключевого слова для него нет. Вопрос звучит легко, поэтому на нём смотрят на связность речи, а следом сразу уточняют детали языка.
Как отвечать
Возьмите бытовой пример и доведите его до кода. Розетка это контракт: обещаны форма контактов и напряжение. Чайник не знает, откуда пришло электричество, а электростанция не знает про чайник. Заменить можно любую сторону, пока обе держат стандарт. Так же работает разъём зарядки или байонет объектива.
В C++ интерфейс это абстрактный класс без состояния: чисто виртуальные методы и виртуальный деструктор.
class Serializer {
public:
virtual ~Serializer() = default;
virtual std::string encode(const Document& doc) const = 0;
};
class JsonSerializer final : public Serializer {
public:
std::string encode(const Document& doc) const override;
};Сразу добавьте, что динамический полиморфизм не единственный путь. Там, где тип известен на этапе компиляции, контракт выражают шаблоном с ограничением через концепт: проверка требований остаётся, а косвенного вызова через таблицу виртуальных функций нет. Выбор между способами и есть содержательная часть ответа: виртуальные функции дают подмену реализации в рантайме и стоят разыменования указателя, шаблоны дают нулевые накладные расходы и раздувают код.
Где спотыкаются
Забывают виртуальный деструктор. Удаление объекта через указатель на базовый класс без него это неопределённое поведение, и деструктор наследника просто не вызовется. Про это спрашивают почти всегда.
Второе: тянут в интерфейс поля и готовые реализации, превращая его в базовый класс ради переиспользования кода. Наследование тогда описывает не контракт, а внутреннее устройство, и любая правка базы задевает всех потомков.
Третье: не помнят про ромб. Когда два интерфейса с общим предком наследуются одним классом, без виртуального наследования появляются две копии базовой части, и обращение к ней становится неоднозначным.