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



Download 1,95 Mb.
Pdf ko'rish
bet83/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   79   80   81   82   83   84   85   86   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
143 
Следующий класс демонстрирует возможное использование этого шаблона. Вмещающему объекту 
Foo
незачем создавать свой образ, как в предыдущих указателях на объекты, поскольку все его переменные 
способны поддерживать свои образы по отдельности. 
class Foo { 
private: 
AutoImage 
some_integer; 
AutoImage 
bar; 
public: 
void 
Rollback() 

some_integer.Rollback(); 
bar.Rollback(); 

void 
Commit() 

some_integer.Commit(); 
bar.Commit(); 

void 
Snapshot() 

some_integer.Snapshot(); 
bar.Snapshot(); 

int ProvideInt() const { return some_integer; } 
void ChanheInt(int new_value) 

if 
(!some_integer.HaveImage()) 
some_integer.Snapshot(); 
int&(some_integer) = new_value; 

const Bar& ProvideBar() const { return bar; } 
Bar& 
UpdateBar() 

if 
(!bar.HaveImage()) 
bar.Shapshot(); 
return 
Bar&(bar); 

}; 
Предполагается, что 
Bar
соответствует необходимым условиям. Последние четыре функции перед тем, 
как обновлять переменную, создают «моментальный снимок» объекта. Для 
int
получение копии по 
определению является константным по отношению к копируемой переменной. При вызове функции, 
изменяющей значение переменной, настает время делать снимок. Для работы с другой переменной, 
bar
, предоставляется как константная, так и неконстантная функция. Конечно, хотелось бы просто 
перегрузить функцию 
ProvideBar()
, чтобы одна перегруженная версия возвращала 
const Bar&
, а 
другая — неконстантный 
Bar&
, но тогда их сигнатуры будут совпадать. Помните: две функции не 
могут иметь одинаковые имена и аргументы и отличаться только типом возвращаемого значения. Я 
никогда не понимал этого ограничения С++, которое запрещает создавать константную и 
неконстантную версию оператора 
->

const Type* operator->() const; 
// Снимок не создается 
Type* operator->() const; 
// Создает снимок 


 144 
Конечно, это намного упростило бы жизнь, но назвать эти загадочные ограничения бесполезными 
нельзя — они дают знатокам С++ хорошую тему для разговоров на семинарах с коктейлями. 
Раз уж речь зашла об ограничениях С++, упомяну еще об одном. Взгляните на приведенный выше код 
класса 
Foo
. Работа некоторых его функций сводится к вызову одной и той же функции для всех 
переменных класса и в более общем случае — базовых классов. Скажем, 
Foo::Commit()
просто 
вызывает 
Commit()
для всех переменных. Весь повторяющийся код приходится писать вручную; в 
языке сильно не хватает макросредств, которые бы позволяли сказать: «Вызвать функцию 
Commit()
для каждой переменной класса». Компилятор знает, как составить список такого рода (и использует его 
в конструкторах), но вам ни за что не скажет. 
Образы указателей 
У шабона 
AutoImage
есть одно довольно занятное применение — им можно воспользоваться для 
создания образов 
*
-указателя. В некоторых ситуациях не хочется создавать лишние копии 
указываемого объекта только чтобы следить за тем, на что ссылался указатель в прошлой жизни. 
Собственно, дело обстоит так каждый раз, когда указатель не является ведущим. Указатель также 
помогает следить за объектами, которые были созданы или уничтожены в процессе транзакции. 
AutoImage f; 
Теперь вы можете восстановить состояние указателя 
f
в начале транзакции, в том числе и 
NULL
. Тем не 
менее, существует веский довод в пользу создания специализированного шаблона для 
*
-указателей — 
необходимость перегрузки оператора 
->
, чтобы указатель образов можно было использовать в левой 
части выражений (что-нибудь типа 
ptr->MemberOfPointer();
). Для 
*
-указателей 
AutoImage
похож 
на глупые указатели, с которыми мы рассправились в начале главы 5. Следующий шаблон больше 
напоминает обычные умные (но не ведущие!) указатели. 
template  
class PtrImage { 
private: 
Type* 
current; 
Type* 
image; 
bool 
have_image; 
// 
Истина, если образ существует 
public: 
PtrImage() : current(NULL), image(NULL), have_image(false) {} 
PtrImage(const 
PtrImage
pi) 
: current(pi.current), image(NULL), have_image(false) {} 
PtrImage& operator=(const PtrImage& pi) 

if (this != &pi) 
current 

pi.current; 
return 
*this; 

PtrImage
operator=(Type* 
t) 
{ current = t; return *this; } 
operator Type*() { return current; } 
Type* operator->() const { return current; } 
bool operator!() { return current == NULL; } 
void 
Snapshot() 

image 

current; 
have_image 

true; 

void Commit() { image = NULL; have_image = false; } 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   79   80   81   82   83   84   85   86   ...   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