C++: библиотека программиста



Download 1,95 Mb.
Pdf ko'rish
bet94/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   90   91   92   93   94   95   96   97   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
165 
virtual void Process(View* v) = 0; 
}; 
class MouseClick : public Event { 
public: 
virtual void Process(View* v) { v->Process(*this); } 
}; 
class View { // Чисто виртуальный базовый класс для видов 
public: 
virtual void Process(MouseClick& ev) = 0; 
virtual void Process(Keystroke& ev) = 0; 
// 
И т.д. 
}; 
Хотя на первый взгляд кажется, что проблема отличается от иерархии 
Number
, присмотритесь 
повнимательнее. Реализация функции 
Process()
класса 
Event
всего лишь «разворачивает» операцию 
и перенаправляет вызов. Поскольку функция 
Event::Process()
является виртуальной, когда дело 
доходит до класса 
View
, точный тип 
Event
уже известен, и компилятор вызывает правильную 
перегруженную версию 
View::Process()

Каждый раз, когда вам захочется забить код типа в переменную класса, чтобы узнать, с каким 
производным классом вы имеете дело, подумайте, нельзя ли переложить хлопоты на компилятор с 
помощью двойной передачи (или одного из описанных ниже вариантов). 
Передача более высокого порядка 
До сих пор мы рассматривали только бинарные функции, однако та же методика распространяется на 
функции с производным количеством аргументов неизвестного типа. Если функция имеет n 
аргументов, передавать придется n раз. Предположим, у вас имеется функция, которая получает три 
аргумента Number и возвращает Number&. Можно устроить, чтобы первый аргумент оказался в левой 
части оператора -> (или .), а дальше начинаются комбинаторные игры. 
class Number { 
protected: 
// ‘this’ – неявный второй аргумент 
virtual Number& fn1(Integer& n1, Number& n3) = 0; 
virtual Number& fn1(Complex& n1, Number& n3) = 0; 
// 
И т.д. для всех типов в первой позиции 
// ‘this’ – неявный третий аргумент 
virtual Number& fn2(Integer& n1, Integer& n2) = 0; 
virtual Number& fn2(Integer& n1, Complex& n2) = 0; 
virtual Number& fn2(Complex& n1, Integer& n2) = 0; 
virtual Number& fn2(Complex& n1, Complex& n2) = 0; 
// 
И т.д. для всех сочетаний 
public: 
// ‘this’ – неявный первый аргумент 
virtual Number& fn(Number& n2, Number& n3) = 0; 
}; 
class Integer : public Number { 
protected: 
// ‘this’ – неявный второй аргумент 
virtual Number& fn1(Integer& n1, Number& n3) 
{ return n3.fn2(n1, *this); } 
virtual Number& fn1(Complex& n1, Number& n3) 


 166 
{ reutrn n3.fn2(n1, *this); } 
// 
И т.д. для всех типов в первой позиции 
// ‘this’ – неявный третий аргумент 
virtual Number& fn2(Integer& n1, Integer& n2) 

// 
Настоящая реализация – известны все три аргумента 

// 
И т.д. для всех сочетаний 
public: 
// ‘this’ – заданный первый аргумент 
virtual Number& fn(Number& n2, Number& n3) 
{ return n2.fn1(*this, n3); } 
}; 
Такой вариант, как и двойная передача, обычно работает быстрее других предлагаемых архитектур. 
Все делается за три элементарных переходя через v-таблицы, а это намного быстрее, чем хеширование 
и просмотр таблиц. Однако он некрасив и быстро становится неуправляемым. Возьмите решение с 
двойной передачей и вообразите, что его сложность начинает возрастать по экспоненте; вы получите 
некоторое представление о том, с чем связано поддержание такой структуры. 
Описанная методика применима и к гетероморфным иерархиям, хотя в результате у вас получится 
«программа-кузнечик»: она совершает головокружительные прыжки из стороны в сторону. Если вы 
проделаете нечто подобное в нетривиальной ситуации, в день сдачи программы прихватите пончиков 
или коробку конфет и будьте необычайно любезны со своими коллегами. Даже если это оптимальное 
решение, его наверняка сочтут… как бы это сказать… в лучшем случае, спорным. 
Если функция имеет больше двух аргументов, число сочетаний растет быстрее, чем грибы после 
дождя. Организуя множественную передачу для нескольких аргументов, серьезно подумайте над 
описанными ниже приемами группировки, уменьшающими количество сочетаний. 
Группировка передач и преобразования 
В реальной жизни редко встречаются уникальные реализации для всех сочетаний левого и правого 
операндов. Например, в любой операции с участием комплексного и какого-то другог числа результат 
будет комплексным. Преобразование некомплексного аргумента в комплексный сокращает количество 
диспетчерских функций. Процесс сокращения матрицы передач я описываю общим термином 
группировка (clustering). На самом деле для большинства задач не существует элегантного, 
универсального и притом головокружительно быстрого способа группировки. К тому же эти способы 
практически никак не связаны с синтаксисом или идиомами С++. Они либо требуют знания типов 
(тема, к которой мы вернемся в следующей главе), либо основаны на логике 
if/then/else
или 
switch/case
, которой мы пытаемся всячески избегать в этой части. 
Существут два основных подхода: 
1. Использовать иерархию классов для обслуживания нескольких сочетаний различных типов 
аргументов одной реализацией. 
2. Сформировать иерархию преобразований и преобразовать один или оба аргумента к более 
универсальному типу, после чего выполнить передачу. 
Их нетрудно спутать, но на самом деле они отличаются. 
Группировка в базовых классах 
Первый подход обычно связан с созданием специфической иерархии классов, которая отображает 
структуру групп. При этом диспетчерские функции поддерживаются только на высоких уровнях 
иерархии классов. При поиске сигнатур компилятор автоматически «преобразует» производные классы 
к промежуточным базовым классам. Такой вариант хорошо подходит лишь для не очень глубоких 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   90   91   92   93   94   95   96   97   ...   144




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish