|
Программирование >> Аргументация конструирования
Iinciude <iostreaKi,h> class Base ( public: virtual void fn() cout << Mi в классе Base\n ; class Subclass : public Base public: virtual void cout Мы в классе SubClass\n ; void b) b.fn () льзуется позднее связывание intint argcs, char * pArgs [ 1 ) { Base Subclass sc; cout Вызываем функцию test(be)\n ; test(be); cout Вызываем функцию teBt(sc)\n ; test(sc) ; return 0; Ключевое слово virtual сообщает C++ о том, что n () является полиморфной функцией-членом. Это так называемое виртуальное объявление f n (} означает, что ее вызовы будут связаны позже, если есть хоть какие-то сомнения по поводу типа аргумента, с которым будет вызываться функция fn () на этапе выполнения. В приведенном фрагменте () вызывается через промежуточную функцию test(). Когда функции test () нередается объект базового класса, b.fnO вызывает функцию Base::fn(). Но когда функции test () передается объект класса Subclass, этот же вызов обращается к функции Subclass : : fn () . Запуск программы приведет к выводу на экран таких строк: Вызываем функцию test(Ьс) Мы в классе Base Вызываем функцию test (sc) Мы в классе Subclass Если вы уже освоились с отладчиком вашей среды C++, настоятельно рекомендую выполнить этот пример в пошаговом режиме. Достаточно объявить функцию виртуальной только в базовом классе. Виртуальность наследуется подклассами автоматически. Однако в этой книге я следую стандарту кодирования, в соответствии с которым функции объявляются виртуальными везде. JhjMMOfuptwe nfuaoiiioiAeHue scuufdcu Поскольку вы уже познакомились с кое-какими деталями объявления виртуальных функций, вернемся к примеру с закусками и посмотрим, как они выглядят в программе. Рассмотрим приведенный ниже фрагмент кода. include <dos.h> нужно дл эования функции sleep (} class Staff!) {}; class Nachos : public Stuff {}; Это и есть наше блюдо Обычная печь class Oven public: virtual voi achos& nachos); необходимые нам функи.га поддержки void turnOnO; включить печь void turnOffO; выключитв печв void insert(Stuff& s) ; поместитв блюдо внутрв void remove(StuffS s) ; вынутв блюдо protected: float temp; void Oven:;cook(Nachosi nachos) { разогреть печв (включитв и ждатв с помощью цикла) пока блюд реется до температуры 3 50°) СигпЭп(); while (temp<350) {} поместитв блюдо внутрв на 15 минут insert(nachos); sleep(i5*60); вынуть и выключить печь remove(nachos); turrOff(); class Microwave : public Oven { public: virtual void nachos); void rotateStuff (Stuff s, s); void nachos) никакого разогрева - температура не нужна сначала поместить блюдо внутрь, затем включить insert(nachos); tur;iOn () ; отть только минуту ( iepes полминуты позернуть блюдо) sleepOO); подождать 30 секунд rotateStuff(nachos); sleep(30); подождать 30 секунд сначала выключите чь, затем вынуть блюдо turnOff О ; remove(nachos); Nachos oven) Смешать ингредиенты Nachos n; теперь приготовить блюдо в любой печи, которая у вас есть oven.cook(n); Съесть результат... return n; Здесь вы видите класс Nachos, который объявлен как подкласс stuff (Блюдо). Класс Oven укомплектован общими функциями - turnOn (), turnoff (), insert () и remove () (с помощью последних двух блюдо помешается в печь и вынимается из нее). Кроме того, класс Oven содержит функцию-член cooli (Nachoss), которая объявлена виртуальной. Функиия cooli (Nachos&) была объявлена виртуальной, поскольку в подклассе Microwave, который наследуется от класса Oven, она работает по-другому. Функция Oven №achos&) разогревает печ до температура 0°, помешает закуски внутрь и готовит их 15 минут. Затем оставшиеся от блюда угольки извлекаются из печи. В отличие от представления класса Oven о приготовлении закусок, функция Microwave: : cook (Nachoss) помещает блюдо внутрь, включает печь на 30 секунд, поворачивает блюдо и ждет еше 30 секунд, прежде чем выключить печь и вынуть блюдо. Все это хотя и превосходно, но всего присказка, сказка - впереди. Функции makeNachos () передается объект Oven некоторого типа. Получив такую oven (печь), она собирает все ингредиенты в объект п и готовит его, вызывав еп. cook (). Какая именно функция иснользуется для этого - Oven : : cook () или Microwave : : cook () , зависит от текущего типа печи. Функция makeNachos (} не имеет об этом представления, да ее это и не интересует. Так чем же так хорош полиморфизм? Во-первых, он возлагает заботу о подробностях работы печи на ее а не на того, кто в ней готовит. Такое разделение труда позволяет переложить детали работы печи на плечи программиста, специализирующегося по печам. Во-вторых, полиморфизм может значительно упростить код. Посмотрите на то, как просто, без использования каких-либо подробностей работы микроволновой печи реализована функция makeNachos!) (я понимаю, что в данном случае эта функция не была бы намного сложнее с деталями, но ведь полиморфизм работает не только с нечами!). И наконец, когда появится новый подкласс печей ConvecticnOven со своей функцией-членом ConvectionOven : : cook (Nachoss), не нужно будет ничего менять в makeNachos {), чтобы воспользоваться новой печью. Полиморфизм автоматически вызовет новую функцию при необходимости. Что и говорить, полиморфизм, раскрывающий перед нами всю мощь наследования, отличная вещь!
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |