Программирование >>  Обобщенные обратные вызовы 

1 ... 76 77 78 [ 79 ] 80 81 82 ... 84


} else {

s.append( n - s.sizeO, с );

template<class charT, class trai ts, class Allocator> void resize(basic string<charT, traits, Allocator>& s, typename Allocator::size type n )

resize( s, n, сНагтО ) ;

Это - один из способов реализации функций resize, не являющихся членами, которые столь же эффективны, как и функции-члены.

assign и +=/append/push back

2. Проанализируйте следующие функции std::string и покажите, могут ли они быть преобразованы в обычные функции-не члены. Обоснуйте ваш ответ.

а) Присваивание, а также +=/append/push back.

Давайте начнем с присваивания. У нас есть щесть - посчитайте сами - шесть видов присваивания. К счастью, этот случай прост: большинство из них уже выражены друг посредством друга, и все они могут быть реализованы с использованием комбинации конструктора и оператора operateг=.

Остаются operator+=, append и push back. Что можно сказать о всех этих многочисленных операциях добавления? Только то, что их схожесть наталкивает на мысль, что членом класса, вероятно, достаточно сделать только одну из них. В конце концов, все они делают одну и ту же работу, даже если немного и разнятся в деталях ее выполнения - например, добавление символа в одном случае, строки в другом и диапазона итераторов в третьем. Все они могут быть реализованы без потери эффективности в качестве обычных функций, не являющихся друзьями класса.

Ясно, что оператор operator+= можно реализовать посредством append, поскольку это указано в стандарте С++.

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

Определение статуса push back требует немного больше усилий, поскольку его семантика определена не в пункте, посвященном классу basic string, а в разделе о требованиях к контейнерам, и здесь мы обнаруживаем, что а.push back(x) - это просто синоним для a.insert(a.endO ,х).

Минутку! - может сказать кое-кто из читателей. - Стандарт С++ гласит, что операторы присваивания должны быть членами, а += - оператор присваивания! И да, и нет. Не углубляясь в детали, можно сказать, что хотя оператор += и перечислен вместе с остальными операторами типа @= как оператор присваивания в фамма-тике С ++, членом класса должен быть только оператор присваивания operator=. Следовательно, следующий пример реализации оператора operator+= как функции-не члена представляет собой совершенно корректный исходный текст С++.

template<class charT, class trai ts, class Anocator> basic strinq<charT, traits, a1locator>& operator+=(basic string<charT, traits, AllocatorxS s,

const basic string<charT, traits, Allocator>& t){ return s.append( t );

tempiate<class charT, class trai ts, class a1locator> Задача 39. Ослабленная монолитность. Часть3: уменьшение std::string 255



basi c stri nq<charT, trai ts, Allocator>&

operator+= (basic string<charT, traits, A!locator>& s,

const chart* p ) { return s.appendC p );

tempiate<class charx, class traits, class Allocatoo basic strinq<charT, traits, Allocator>& operator+=(basic string<charT, traits, Allocator>& s,

CharT с ) { return s.appendC 1, с );

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

insert

б) insert.

Тем, кому кажется, что шести версий assign и шести версий append многовато

для одного класса, рекомендую запастись валерьянкой: сейчас мы рассмотрим восемь версий insert.

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

Однако у нас восемь функций insert. Какую из них (или какие) сделать членом класса? Пять из восьми функций insert непосредственно определены посредством функции insert с тремя параметрами, да и остальные версии вполне можно эффективно реализовать при помощи этой трехпараметрической функции. Поэтому функцией-членом мы делаем именно ее, а все остальные могут быть обычными функциями, не являющимися друзьями класса.

Небольшой перерыв

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



Задача 40. Ослабленная монолитность.

Часть 4: новый std:: stri ng Сложность: 6

в этой задаче мы наконец полностью разберемся с классом std: .-string и посмотрим, как выглядит строковый класс минимального размера.

Вопрос для новичка

1. Может ли string::erase быть функцией-не членом? Обоснуйте свой ответ. Вопрос для профессионала

2. Проанализируйте оставшиеся функции-члены std: :string и покажите, могут ли они быть сделаны обычными функциями-ие членами. Обоснуйте ваш ответ.

а) replace

б) сору и substr

в) compare

г) Семейство find (find, find * и rfind)

Решение

Прочие операции, которые могут не быть членами

Нам осталось рассмотреть только несколько функций, и, как вы увидите, все они могут быть реализованы как обычные функции, не являющиеся друзьями класса.

erase (2 - все версии, кроме iter, iter )

replace (8 - все версии, кроме iter, iter, num, char и шаблонных)

copy

substr

compare (5)

fi nd (4)

rfi nd (4)

fi nd fi rst of (4)

find last of (4)

find first not of (4)

f i nd l ast nоt of (4)

Небольшой перерыв на кофе

1. Может ли string::erase быть функцией-не членом? Обоснуйте свой ответ.

После того как мы рассмотрели и разобрались с тремя десятками версий функций assign, append, insert и replace, для вас будет большим облегчением услышать, что есть только три версии функции erase. После всего, с чем мы имели дело, это занятие - разминка на время перерыва для того, чтобы выпить чашечку кофе...

Тройка функций-членов erase малоинтересна. Как минимум одна из этих функций должна быть членом (или другом), другого пути эффективной реализации этих



1 ... 76 77 78 [ 79 ] 80 81 82 ... 84

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