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



Download 1,95 Mb.
Pdf ko'rish
bet66/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   62   63   64   65   66   67   68   69   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
109 
class Fn { 
private: 
int 
number; 
public: 
f(int n) : number(n) {} 
void operator() () { do_something(number); } 
}; 
void callbackfn(Fn); 
void p(int n) 

callbackfn(Fn(n)); 

void callbackfn(Fn fn) 

// 
Что-то делаем 
fn(); // 
Вызвать «функцию» fn с помощью функции operator() 

Весь секрет кроется в двух выражениях. Функция 
callbackfn(Fn(n))
передает функции анонимный 
экземпляр класса 
Fn
. Аргумент его конструктора содержит информацию, включаемую в 
«псевдозамыкание», которое поддерживается переменными класса 
Fn
. Выражение 
fn();
может 
показаться обычным вызовом функции, но на самом деле в нем вызывается операторная функция 
operator()
класса 
Fn
. В свою очередь, эта функция вызывает глобальную функцию 
do_something
с
использованием данных замыкания. И кому после этого нужен Паскаль? 
Операторная функция 
operator()
может вызываться с произвольным набором аргументов. Чтобы 
добавить новые аргументы, укажите их во вторых скобках в объявлении класса. Также разрешается 
многократная перегрузка оператора 
()
с разными сигнатурами. Ниже приведен тот же пример, в 
котором одна из версий операторной функции 
operator()
вызывается с аргументом. 
class Fn { 
private: 
int 
number; 
public: 
f(int n) : number(n) {} 
void operator() () { do_something(number); } 
void operator() (char* s) 

do_something(number); 
cout << “Что-то делаю с ” << s << endl; 

}; 
void callbackfn(Fn); 
void p(int n) 

callbackfn(Fn(n)); 



 110 
void callbackfn(Fn fn) 

// 
Что-то делаем 
fn(“callbackfn”); 

Эта маленькая идиома выглядит довольно изящно, однако того же эффекта можно добиться и без 
оператора 
()

class Fn { 
private: 
int 
number; 
public: 
f(int n) : number(n) {} 
void do_something() () { ::do_something(number); } 
void do_something() (char* s) 

do_something(number); 
cout << “Что-то делаю с ” << s << endl; 

}; 
void callbackfn(Fn); 
void p(int n) 

callbackfn(Fn(n)); 

void callbackfn(Fn fn) 

// 
Что-то делаем 
fn.do_something(“callbackfn”); 

Как видите, с таким же успехом можно воспользоваться именем любой функции класса. Единственная 
причина для использования оператора 
()
— в том, что он предельно ясно выражает ваши намерения. 
Если класс существует лишь для того, чтобы обслуживать обратные вызовы подобного рода, 
пользуйтесь оператором 
()
; в противном случае пользуйтесь обычными функциями класса. 


Коллекции, 
курсоры и 
итераторы 
Проблема проектирования и реализации классов-коллекций (совокупностей объектов, находящихся 
под управлением другого объекта) стара, как само объектно-ориентированное программирование. Нет 
смысла повторять здесь все, что можно прочитать в других книгах о всевозможных коллекциях — 
изменяемых, сериализуемых, индексируемых и т. д. Если вам нужна информация о структурах данных 
и сопутствующих трансформациях, начните с изучения классов-коллекций SmallTalk и затем 
переходите к коммерческим библиотекам классов C++, рекламой которых забиты все журналы по 
программному обеспечению. Я же собираюсь сосредоточить ваше внимание на тех С++-измах, 
благодаря которым коллекции укладываются в мистическое учение программирования на C++ 
независимо от используемых структур данных и иерархий классов. 
В начале этой главы рассматриваются индексируемые коллекции — то есть те, в которых некоторый 
объект используется в качестве индекса для получения другого объекта, скрытого глубоко в недрах 
коллекции. Мы воспользуемся оператором 
[]
, чтобы коллекция выглядела как абстрактный массив. 
Дело даже не в том, что программа от этого обычно становится более понятной — в этом подходе за-
действованы многие идиомы, используемые для коллекций. После знакомства с курсорами и их 
собратьями итераторами мы перейдем к изощренным коллекциям, модифицируемым в процессе 
перебора. 
Массивы и оператор [] 
Оператор 
[]
чрезвычайно гибок и универсален. К сожалению, большинство программистов C++ об 
этом и не подозревает. 
Проверка границ и присваивание 
Ниже приведен простой пример перегрузки оператора 
[]
— массив, который при обращении к 
элементу проверяет, принадлежит ли индекс границам массива, и в любых ситуациях ведет себя более 
или менее разумно (или по крайней мере безопасно). 
class ArrayOfFoo { 
private: 
int 
entries; 
Foo** 
contents; 
// 
Вектор Foo* 
static Foo* dummy;
// Для индексов, выходящих за границы массива 
public: 
ArrayOfFoo() : entries(0), contents(NULL) {}; 
ArrayOfFoo(int size) : entries(size), contents(new Foo*[size]) {}; 
~ArrayOfFoo() { delete contents; } 
Foo*& 
operator[](int 
index) 

Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   62   63   64   65   66   67   68   69   ...   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