Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Глава22.Знакомствосвиртуальнымифункциями-членами:настоящиел




class Base

 

virtual void f

cout << "Мы в классе Base\n";

}

};

class Subclass : public Base

 

virtual void

{

cout << "Мы в классе

 

 

void       b)

 

();              позднее связывание

)

int     argcs, char*

 

Base Subclass sc;

cout << "Вызываем функцию

 

cout << "Вызываем функцию

 

return 0;

 

Ключевое слово virtua l сообщает C++ о том, что n () является полиморфной функцией-членом. Это так называемое виртуальное объявление f n (} означает, что ее вызовы будут связаны позже, если есть хоть какие-то сомнения по поводу типа аргу- мента, с которым будет вызываться функция f n () на этапе выполнения.

В  приведенном  фрагменте           () вызывается через  промежуточную  функцию (). Когда функции tes t () передается объект базового класса,                          вызывает функцию       :  n ().         Но  когда         функции tes t () передается                              объект класса

Subclass, этот же вызов обращается к функции Subclass : :             () .

Запуск программы приведет к выводу на экран таких строк:

Вызываем функцию Мы в классе Вызываем функцию Мы в классе

 

Если вы уже освоились с отладчиком вашей среды C++, настоятельно ре- комендую выполнить этот пример в пошаговом режиме.

 

 

Достаточно объявить функцию виртуальной только в базовом классе. Вир- туальность наследуется подклассами автоматически. Однако в этой книге я следую стандарту кодирования, в соответствии с которым функции объ- являются виртуальными везде.

 


Часть IV, Наследование


Поскольку вы уже познакомились с кое-какими деталями объявления виртуальных вернемся к  примеру с и посмотрим, как они выглядят в про-

грамме. Рассмотрим приведенный ниже фрагмент кода.

//нужно  для                                  функции

class       !) {};

class Nachos : public Stuff        и есть наше блюдо

 

// Обычная печь class Oven

{

 

virtual void         nachos);

//необходимые нам     поддержки void //включить печь

void               //выключить печь

void          s) ; //поместить блюдо внутрь

void          s) ; //вынуть блюдо

 

protected:

float temp;

};

void                nachos)

{

//pa   печь (включить и ждать с    цикла) блюдо  до температуры 3

 

while (temp<350) {}

//поместить блюдо внутрь на минут

 

;

 

//вынуть и выключить печь

;


turrOff();

}

 

{


 

 

:   Oven


virtual void         nachos); void

 

void                     nachos)

{

— температура не нужна

//сначала поместить блюдо внутрь, затем включить

 

;

/                                    минуту

// ( полминуты позернуть блюдо)

//подождать 30 секунд

 

sleep(30);      //подождать 30 секунд

 

Глава22.Знакомство свиртуальнымифункциями-членами:настоящиели


//сначала выключить   затем вынуть блюдо turnOff();

 

 

Nachos              oven)

f

//Смешать ингредиенты Nachos n;

//теперь приготовить блюдо

//в любой печи, которая у вас есть

 

//Съесть результат... return

}

Здесь вы  видите  класс                     который объявлен как подкласс stuf f (Блюдо).

Класс Oven укомплектован                   функциями turnOn () , turno f f (), inser t () и remove () (с помощью последних двух блюдо помешается в печь и вынимается из нее). Кроме того, класс Oven содержит  функцию-член cook          ), которая объ- явлена виртуальной.

cook                     была объявлена виртуальной, поскольку в подклассе Microwave, который наследуется от класса Oven, она работает по-другому. Функ- ция Oven:                                           разогревает печь  температуры     помешает закус- ки внутрь и готовит их 15 минут. Затем оставшиеся от блюда угольки извлекаются из печи. В отличие от представления класса Oven о приготовлении закусок, функ- ция Microwave: : cook                              помещает блюдо внутрь, включает печь на 30 се- кунд, поворачивает блюдо и ждет еше 30 секунд, прежде чем выключить печь и вы- нуть

Все это хотя и превосходно, но всего               присказка, сказка — впереди. Функции makeNachos () объект Oven некоторого типа. Получив такую oven (печь), она собирает все ингредиенты в объект п и готовит его, вызывая cook (). Какая именно функция используется для этого Oven : : cook () или Microwave : : cook () , зависит от текущего типа печи. Функция makeNachos (} не имеет об этом представ- ления, да ее это и не интересует.

Так чем же так хорош полиморфизм? Во-первых, он возлагает заботу о подробно- стях работы печи на ее а не на того, кто в ней готовит. Такое разделе- ние труда позволяет переложить детали работы печи на плечи программиста, специа- лизирующегося по печам.

Во-вторых, полиморфизм может значительно упростить код. Посмотрите на то, как просто, без использования подробностей работы микроволновой печи реализована функция makeNachos!) (я понимаю, что в данном случае эта функция не была бы намного сложнее с деталями, но ведь полиморфизм работает не только с печами!). И наконец, когда появится новый подкласс  печей                                                                                 со своей  функцией-членом                                    :          не нужно будет ничего менять в makeNachos {), чтобы воспользоваться новой печью. Полиморфизм автома- тически вызовет новую функцию при необходимости.

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

 

 






Часть IV. Наследование


не

tfufuni/альной

Даже если вы считаете, что каждая функция вызывается с использованием позд- него связывания, это отнюдь не означает, что так и есть на самом деле.

C++ на этапе компилирования никак не указывает, какое связывание было использовано — ранее или позднее.

 

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

 

class Base

{

 

virtual void       x)

{

cout << "Мы в классе Base, int x " << x <<

 

 

c{lass : Base v{irtualvoidfn(floatx)

cout « "Мы в классе float x = " « x « "\n";

 

 

void       b)

 

int i =

fn    //Здесь не          позднее связывание float f =

//И здесь тоже не используется

 

int     argcs, char*

{

Ease Subclass sc;

cout << "Вызываем функцию test;

cout << "Вызываем функцию

;

return

 


Поделиться:



Последнее изменение этой страницы: 2019-04-19; Просмотров: 193; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.03 с.)
Главная | Случайная страница | Обратная связь