Одни и те же термины могут использоваться для разных вещей, что и происходит здесь.
«Абстрактный» в C ++ означает метод, который вообще не имеет реализации (вы не можете создать экземпляр объекта с элементами Abstract.)
«Абстракция» - это просто понятие «моделирование». Моделирование упрощает внешний вид чего-то сложного, игнорируя некоторые детали. В программировании вы хотите разбить операции и концепции на компоненты, а для каждого компонента абстрагировать детали от внешних компонентов, которые не влияют на работу текущего компонента.
Программный «Интерфейс» - это способ реализации «Абстракции». Вместо того, чтобы иметь весь исходный код и внутренние операции компонента, вы видите только те операции, которые соответствуют тому, как вы используете объект. «Интерфейс» в C ++ реализован путем пометки всех методов класса как «абстрактных» (также называемых «чисто виртуальными»). Это делается путем помещения '= 0' после объявления метода, но перед точкой с запятой. Метод должен быть помечен как «виртуальный», чтобы это было допустимо.
Другими словами, абстрактный класс C ++ - это класс, в котором есть хотя бы один чисто виртуальный метод, а интерфейс реализован в C ++, делая все функции-члены чисто виртуальными.
Инкапсуляция - это нечеткий термин, но для меня это означает технику реализации абстракции. Это означает «сокрытие информации». Вы скрываете внутренние детали того, как объект выполняет свой «контракт». Контракт выражается через интерфейсы, что, на мой взгляд, является более мощной формой абстракции. Любой класс C ++ с защищенными или закрытыми членами использует инкапсуляцию, но класс, реализующий только чисто виртуальные методы, описывает контракт, обещая предоставить определенные сервисы, для которых вам нужно абсолютно ничего не знать о том, как они реализованы, или о других сервисах, которые тот же объект может воплощать в жизнь.
Один и тот же объект может заполнять несколько контрактов, и, предоставляя несколько непересекающихся интерфейсов, он не заставляет клиентов знать обо всех вспомогательных функциях объекта. Например, объект может сообщать вам остаток на банковском счете, а также может быть сериализован / десериализован в базу данных. Вы могли бы просто иметь один класс со всеми этими операциями, представленными как функции-члены. Я предпочитаю определять два интерфейса: «IDatabaseSerializable» и «IBankAccount», и помещать соответствующие операции в соответствующие интерфейсы и наследовать оба интерфейса в моем классе реализации. Затем клиенты, которые заботятся только о банковских балансах, видят как можно меньше дополнительной информации, а база данных видит только те операции, которые ей нужны.