Abstract Классы и C ++

Abstract Классы и C ++ - манекены

C ++ поддерживает позднюю привязку , , когда она разрешает вызов метода на основе времени выполнения тип (или динамический тип) целевого объекта, а не его объявленный тип (или статический тип). Это показано в следующем фрагменте кода C ++:

 #include с использованием пространства имен std; class oven {public: virtual void cook () {cout << "приготовление с духовкой" << endl;}}; класс Микроволновая печь: общественная печь {public: virtual void cook () {cout << «приготовление пищи с помощью микроволновой печи» << endl;}}; void prepareMeal (духовка и печь) {печь. cook ();} 

В функции prepareMeal () вызов духовки. cook () может перейти к Oven:: cook () или MicrowaveOven:: cook () в зависимости от времени выполнения («фактический») типа объекта печи.

Здесь важно критическое ключевое слово. Без него метод cook () будет связан раньше, основываясь на типе времени компиляции, и каждый раз вызывать Oven:: cook (). Объявленный виртуальным в классе Oven, этот метод считается виртуальным во всех подклассах, но не повторяет декларацию, чтобы понять читателей.

Следующая простая программа демонстрирует этот принцип на практике:

 int main () {Духовка; prepareMeal (печь); Микроволновая печь. prepareMeal (МО); return 0;} 

В этой программе вызов cook () генерирует два разных выхода в зависимости от типа духового шкафа:

 Кулинария с духовкой Кулинария с микроволновой печью 

Это не всегда так, что метод базового класса может быть определен. Рассмотрите вопрос о духовке более тщательно. Существует несколько различных типов печей: обычные печи, конвекционные печи и микроволновые печи, но можно утверждать, что нет реальной печи, которая не принадлежит к одному из этих подклассов. Возможно, вы сможете сказать, как различные типы печей выполняют операцию повара - то есть, что нужно сделать, например, для метода Commonalven:: cook () и MicrowaveOven:: cook (). Вероятно, невозможно определить, какие действия должна выполнять печь:: cook ().

Вы не можете просто оставить Oven:: cook () необъявленным на строго типизированном языке, таком как C ++. Однако вы можете объявить метод, но оставьте его unimplemented , если реализация не существует. Для этого используется следующий любопытный синтаксис:

 class Oven {public: virtual void cook () = 0;}; 

Этот код объявляет метод Oven:: cook (), связанный поздно, но не реализующий метод. Фактически, это идет дальше, говоря, что метод не будет реализован. В C ++ такой метод называется чисто виртуальным . Программисты на С ++ также используют термин, предпочтительный для многих других строго типизированных языков компьютера: abstract .Класс Духов считается абстрактным.

Реферат представляет свойство, которое, как вы знаете, обладает классом, но не знает, как реализовать однозначно в текущем классе.

Класс является абстрактным, если он содержит один или несколько чистых виртуальных методов. Значимость этого заключается в том, что вы не можете создать экземпляр абстрактного класса. Таким образом, больше не допускается следующее:

 int main () {Духовка; prepareMeal (печь); return 0;} 

Причина этого довольно проста: если вы создали объект класса Oven, а затем попытались вызвать духовку. cook (), что должен делать компилятор?

На более философском уровне хорошо сказать, что есть общий термин, называемый Духовкой, который описывает обычные печи и микроволновые печи и конвекционные печи. Этот термин является обычной концепцией, потому что она связывает сходства во всех этих подклассах. Но нет ни одного экземпляра печи, которая не является одним из подклассов Духовки.

Подкласс абстрактного класса сам является абстрактным до тех пор, пока все чистые виртуальные методы не будут переопределены не абстрактными (то есть конкретными ) версиями. Таким образом, класс MicrowaveOven в предыдущем фрагменте кода не является абстрактным - даже если печь была абстрактной - потому что она переопределяет cook () с ее собственной конкретной версией.

Обратите внимание: нет ничего плохого в функции prepareMeal (), определяемой следующим образом:

 void prepareMeal (духовка и печь) {печь. cook ();} 

Даже если аргумент объявлен как духовой шкаф, его можно вызвать только с помощью некоторого подкласса духовки, такого как MicrowaveOven или Commonalven, для которого определен cook ().