Главная » Просмотр файлов » А. Александреску - Современное проектирование на C++

А. Александреску - Современное проектирование на C++ (1119444), страница 32

Файл №1119444 А. Александреску - Современное проектирование на C++ (А. Александреску - Современное проектирование на C++) 32 страницаА. Александреску - Современное проектирование на C++ (1119444) страница 322019-05-09СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 32)

Можно предположить, что класс Рипстог не будет скомпилирован вовсе, поскольку в каждой специализации класса Рипстогтюр1 опре- делен только один оператор О, а не группа, как в классе Рипстог, Трюк заключается в том, что в языке С++ функции-члены шаблонных класаов не конкретизируются, поко они не выэвоны. Пока не вызывается неправильный оператор О, компилятору все равно.

При вызове перегруженного оператора О, не имеющего смысла, компилятор попытается сгенерировать его тело и обнаружит несоответствие. // Определяем фуиктор, получающий параметры типа эпт и доиЫе, // и возвращающий значение типа доиЫе. Рипсаог<доиЫе, ттяяьтэт 2(зпа, доиЫе)> юугипссог„' // Вызываем его. // генерируется тело оператора орегатогО(с)оиЫе, эпа). доиЫе геэи1а = юугипстог(4, 5.6); // Неверный вызов, доиЫе геэи1т = юукипстогО; //ошибка! // оператор орегасогО О неверен, // потому что он не определен в классе // Рипстог|юр1<доиЫе, ТУРеь15Т 2(1пт, доиЫе)>. Благодаря этому тонкому трюку класс Рипстог не обязательно частично инициали- зировать для нуля, одного, двух и больше параметров —.

это лишь приведет к дубли- рованию кода, Достаточно определить все версии и позволить компилятору генериро- вать только одну из них. Теперь все вспомогательные аредства созданы, и можно приступать к определению конкретных классов, производных от класса Рипстогтщр1. вэ.6. РабОта С фуНКтсраМИ Начнем работать с функторами. Функторы представляют собой экземпляры классов, в которых определен оператор О, как в классе Рипссог (т.е.

объект класса гипстог и сам являетая функтором). следовательно, конструктор клаааа Рипстог, получаюший объект класса Рипссог в качестве параметра, является шаблоном, параметризованным типом этого функтора. сеюр1ате <турепаще а, с1аьэ тьбэт> с1аээ Рипстог ( как и раньше риЫ)с: аеюр1ате кс1аээ Рип> Рипстог(сопят Рип$ ~ип)," Для того чтобы реализовать этот конструктор, нам нужен простой шаблонный класа Рипстогнапд1ег, производный от класса Рипстог|юр1<я, ть1эс>. Этот класс хранит объект типа Рип и передает ему оператор О. Реализуя оператор О, мы прибегнем к описанному выше трюку.

Чтобы избежать определения слишком большого количества параметров класса Рипссогнапд1ег, сделаем шаблонным параметром саму конкретизацию класса Рипстог. Этот единственный параметр содержит остальные, поскольку он предусматривает внутренний оператор турее)е~. 132 Часть!1, Компоненты севр1асе <с1азд РагепСГипссог, Сурепаве Гип> с1азз гипссогнапд1ег риЫ !с гипссогтвр! сурепаве Рагепсгипссог::нези!стуре, Сурепаве РагепСГипстог::Рагвь!зт > ( риЫ1 с: суредеГ сурепаве Рагепсгипссог:нсези!стуре нези!стуре; гипссогнапд1ег(сопзс гипб Гип) : Гип (Гип) () гипссогнапд1ег* с1опе() сопзс ( гесигп пеи гипссогнапд1ег(+сп!з); нези!стуре орегасогО О ( гесигп Гип 0; ) яеаи1стуре орегасого(сурепаве Рагепсгипссог:: Рагв1 р1) гесигп Гип (р1); ) веьи1 стуре орегасого (сурепрве Рагепсгипссог:: Рагв1 р1, Сурепаве РагепСГипстог::Рагв2 р2) ( гееигп Гип (р1,р2); ) рг1часе: гип Гоп ; ); Класс гипссогнапд1ег почти не отличается от класса гипссог.

Он переадресовывает запросы сохраняемой переменной-члену. Основное отличие заключается в том, что функтор хранится как значение, а не как указатель, Вот почему функторы являются неполиморфными типами с обычной семантикой копирования. Обратите внимание на внутренние типы Рагепсгипссог::яези1стуре, Рагепсгипссог:: Рагв1 и РагепсГипссог.":Рагв2. В классе гипссогнапд1ег реализован простой конструктор, функция клонирования и несколько версий оператора О. Компилятор сам выберет правильный вариант.

Если перегрузка оператора О выполнена неверно, компилятор выдаст сообщение об ошибке. В реализации класса гипссогнад1ег нет ничего необычного, но это вовсе не означает, что она тривиальна. В следующем разделе будет показано, какой универсальностью обладает этот небольшой шаблонный класс. С помощью объявления класса гипссогнапд1ег легко написать шаблонный констРуктор класса гипссог. севр1асе <сурепаве я, с1азз тьззс> севр1асе <сурепаве гип> гипссог<а, тсз'зс>::гипссог(сопзс гипс Гип) зртвр! (пев гипссогнапд1ег<гипссог, гип>(Гип)); Глава 5.

Обобщенные функторы Злесь нет никакой ошибки. Два шаблонных параметра указаны правильно: выражение темр1асе <с1ааа я, с1азз ть!зс> относится к классу еипссог, а семр1ате <сурепаве еип> является параметром конструктора. В стандарте языка такой код называется "шаблонным определением члена вне класса" ("оцт-оГ-с!ааз шешбег !еепр!а(е дейл!с!оп").

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

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

Информация о типах сохраняется в динамическом указателе на класс ецпссогтшр1. Хотя мы написали лишь часть кода (просто несколько функций, состоящих из одной строки), уже можно кое-что проверить. // предположим, что файл ецпстог.п включен // в реализацию класса еипстог «!пс1нде "ецпстог.!з" «тпс1иде <чозтгеам> // для небольших программ на с++ можно применять // директиву оадпд оз!пд памезрасе зсд; // Определяем тестируемый фуннтор зсгцсг тезгеипссог ( чо!д орегасогО(!пт 1, доиЫе д) соиг « "тезгеопссог::орегатогО(" «! « ", " « д « ") са11ед.

~п"; дпт шачпО ( тезтеипстог т; Еипстог<чо!д, туевьтвт 2(!пт, доиЫе)> сшд(б); смд(4, 4.5); Эта маленькая программа вывалит на печать следующую строку. тезтемпссог::орегасогО(4, 4.5) са11ед. Следовательно, мы достигли своей цели. Теперь можно идти дальше. 5Л. Один пишем, два в уме Читая предыдущий раздел, не залавались ли вы вопросом: "Почему мы не начали с реализации простых указателей на обычные функции?". Зачем мы перескочили сразу к 134 Часть |!. Компоненты функторам, шаблонам и т.п.? Ответ прост — в настоящее время поддержка указателей на обычные функции улге реааизоввна. Изменим немного нашу тестовую программу. Ф пс1цг(е Ч цпстог.)з" Фпс1цде <)озтгеав> цв(пц павезрасе зтг); // Определяем тестируемую функцию чотг) тезтгцпст(оп (з'пт 5, доцЫе д) ( соцт « "тезтгцпст)оп(" «( « ", " « г) « ") са11ед. 'хп"; тпт вазпО гцпссог<чоз'г), тчрвьт5т 2(зпт, г(оцЫе)> свд(тезтгцпст(оп); // выведет на печать строку // "тезтгцпст(оп(4, 4.5) са11ед." свд(4, 4.5); Объяснение этого приятного сюрприза кроется в способе вывода шаблонных параметров.

Когда компилятор обнаруживает класс гцпстог, созданный из функции тезтьцпстз'оп, он вынужден проверить шаблонный конструктор. Затем компилятор конкретизирует шаблонный конструктор шаблонным аргументом чо(б (в) (зот, г)оцЫе), представляющим собой тип значения, возвращаемого функцией тезтгцпстз'оп. Конструктор конкретизирует класс гцпстогнапд1ег<яцпстог<...>, чеза (в)(зпт, доцЫе)>.

Следовательно, переменная бцп в классе яцпссогнапд1ег также имеет тип чо)б (в)()пт, доцЫе). При вызове оператора гцпссогнапд1ег<...>::орегасогО он передается функции %я О. Это вполне допустимая синтаксическая конструкция, означающая вызов функции с помощью указателя. Итак, класс гцпссогнапд1 ег поддерживает указатели на внешние функции по двум причинам: благодаря синтаксической схожести указателей на функции и функторов и особенностям механизма вывода типов в языке Сч-ь. Однако есть одна проблема.

(У всех есть свои недостатки, не так ли?) При перегрузке функции тезтгцпст(оп (или любой другой функции, которая передается классу гцпстог<...>) возникает неопределенность. Ее причина заключается в том, что при перегрузке функции тезтгцпстзоп тип символа тезтгцпст)оп становится неопределенным. Чтобы проиллюстрировать этот факт, поместим перегруженную версию функции тезтгцпст) оп прямо перед функцией вази. // объявление перегруженной функции тезтгцст(оп // (определение не обязательно) чо(д теэтяцпст)оп((пт); Неожиданно компилятор сообшает, что не может распознать, какую из перегруженных версий функции тезтгвпст)оп следует использовать. Посколъку есть две функции с именем тезтьцпст) оп, одного имени для идентификации функции недостаточно. В сущности, при перегрузке есть два способа идентифицировать конкретную функцию: с помощью инициализации (или присваивания) или с помощью приведения типов.

Проиллюстрируем оба метода. // как и выше, функция тезтяопст(оп перегружена (пт ва)пО ( // для удобства используется оператор туребе1 135 Глава б. Обобщенные функторы суредеб чо)д (*тргип)(зпс, доиЫе); // способ 1: инициализация тргип рг = тезсгипсс!оп; гипссог<чосд, тчгвьсвт 2(дпс, доиЫе)> свд1(4, 4.5); // способ 2: приведение типов гипссог<чосд, дпс, доиЫе)> свд2( зсасзс сазс<тргип>(тезсгипссзоп)); // все правильно! д2(4, 4.5); Оба способа инициализации позволяют компилятору распознать требуемую версию функции тезсгисс1оп, которая должна получать параметры типа зпс и доиЫе, а возвращать — значение типа чо)д, 5.8. Преобразование типов аргументов и возвращаемого значения В идеале преобразование типов лля функторов должно выполняться так же, как и при вызовах обычных функций.

Тогда можно было бы написать примерно такой код. Вдпс1иде <зтгдпй> к!пс1иде <чозсгеав> Ипс1иде "гипссог.Ь" изз'по павезрасе зсд; // Аргументы игнорируются — в данном примере // они не представляют интереса сопзс сЬаг* тезсгипссчоп(доиЫе, доиЫе) аеас)с сопзс спаг Ьиттег() = "не11о, иог1д!"; // можно вернуть указатель на статический буфер гесигп Ьи(1ег; спс вазпО гипссог<зсгз'по тчгессБт 2(дпс, 1пс)> свд(тезсгипссдоп); // должен выводить на печать строку ?вог1д!" соис « свд(10, 10).зиЬзсг(7); Несмотря на то что сигнатура фактической функции тезсгипссз'оп немного отличается (она получает два параметра типа доиЫе и возврашает константу типа спать), ей можно поставить в соответствие функтор гипсСог<зтг!пй, ттядссвт 2(!пс, дпс)>.

Предполагается, что это возможно, поскольку тнп 1пс можно неявно преобразовать в тип доиЫе, а значение типа сопл сЬаг* — в тип зсгдпй. Если класс гипссог не поддерживает те же преобразования, что и язык С++, то такие жесткие ограничения следует считать неоправданными.

Характеристики

Список файлов книги

Свежие статьи
Популярно сейчас
Как Вы думаете, сколько людей до Вас делали точно такое же задание? 99% студентов выполняют точно такие же задания, как и их предшественники год назад. Найдите нужный учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6485
Авторов
на СтудИзбе
303
Средний доход
с одного платного файла
Обучение Подробнее