Программирование >>  Аргументация конструирования 

1 ... 72 73 74 [ 75 ] 76 77 78 ... 108


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 {), чтобы воспользоваться новой печью. Полиморфизм автоматически вызовет новую функцию при необходимости.

Что и говорить, полиморфизм, раскрывающий перед нами всю мощь наследования, отличная вещь!



1 ... 72 73 74 [ 75 ] 76 77 78 ... 108

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика