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



Download 1,95 Mb.
Pdf ko'rish
bet50/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   46   47   48   49   50   51   52   53   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
77 
}; 
class Pbar : public PFoo { 
public: 
PBar() : PFoo() {} 
PBar(Bar* p) : PFoo(p) {} 
operator Bar*() { return (Bar*)addr; } 
Bar* operator->() { return (Bar*)addr; } 
}; 
pBar pb(new Bar); 
pFoo pf(pb);
// Работает, потому что PBar является производным от PFoo 
pf->MemberOfFoo(); // Работает благодаря PFoo::operator-> 
Этот вариант будет работать, если вас не огорчают многочисленные копирования/вставки текста и (в 
зависимости от компилятора) предупреждения о том, что 
РВаr::operator->()
скрывает 
PFoo::operator->()
. Конечно, такое решение не настолько элегантно, как встроенные типы 
указателей шаблона 
Ptr

Арифметические операции с указателями 
Ниже показан пример арифметических операторов, обеспечивающих работу операций 
сложения/вычитания для умных указателей. Для полной, абсолютно совместимой реализации к ним 
следует добавить операторы 
++
и 
--

template  
class Ptr { 
private: 
Type* 
pointer; 
public: 
Ptr() : pointer(NULL) {} 
Ptr(Type* p) : pointer(p) {} 
operator Type*() { return pointer; } 
ptr_diff operator-(Ptr p) { return pointer – p.pointer; } 
ptr_diff operator-(void* v) { return ((void*)pointer) – v; } 
Ptr operator-(long index) { return Ptr(pointer – index); } 
Ptr operator-=(long index) { pointer -= index; return *this; } 
Ptr operator+(long index) { return Ptr(pointer + index); } 
Ptr operator+=(long index) { pointer += index; return *this; } 
}; 
Важно понимать, чем 
ptr_diff
отличается от целого индекса. При вычитании одного адреса из 
другого результатом является смещение, как правило, выраженное в байтах. В случае прибавления 
целого к указателю адрес изменяется на размер объекта, умноженный на целое. Помните: в C++, как и 
в С, указатель ссылается не на один объект, а на теоретический массив объектов. Индексы в описанных 
выше перегруженных операторах представляют собой индексы этого теоретического массива, а не 
количества байт. 
После всего сказанного я бы не советовал пускаться на эти хлопоты для умных указателей — не из-за 
лени, а потому, что в этом случае вы обрекаете себя на решения, которые не всегда желательны. Если 
дать пользователю возможность складывать и вычитать указатели, вам неизбежно придется 
поддерживать идею, что указатель всегда индексирует воображаемый массив. Как выяснится в 
следующих главах, многие варианты применения умных указателей не должны или даже не могут 
правильно работать с парадигмой массива. 


 78 
Во что обходится умный указатель? 
Объект класса, не содержащего виртуальных функций, занимает столько места, сколько необходимо 
для хранения всех его переменных. В рассмотренных выше умных указателях используется всего одна 
переменная — 
*
-указатель; то есть размер умного указателя в точности совпадает с размером 
встроенного указателя. Хороший компилятор C++ должен специальным образом обрабатывать 
тривиальные подставляемые функции, в том числе и находящиеся в шаблоне умного указателя. 
template  
class Ptr { 
private: 
Type* 
pointer; 
public: 
Ptr() : pointer(NULL) {} 
Ptr(Type* p) : pointer(p) {} 
operator Type*() { return pointer; } 
Type* operator->() { return pointer; } 
}; 
В частности, использование оператора 
->
из этого шаблона не должно требовать никаких 
дополнительных вычислений по сравнению со встроенными указателями. Как всегда, обращайте 
особое внимание на слова хороший и должно. В хорошей реализации описанные выше умные 
указатели не требуют никаких дополнительных расходов. По крайней мере, хуже пока не стало. 
Применения 
Умные указатели — существа на редкость полезные, и мы проведем немало времени, изучая их 
применение на практике. Для простых умных указателей, рассматриваемых в этой главе, находятся 
столь же простые, но мощные применения. 
Разыменование значения NULL 
Рассмотрим одну из вариаций на тему умных указателей: 
template  
class SPN { 
private: 
Type* 
pointer; 
public: 
SPN() : pointer(NULL) {} 
SPN(Type* p) : pointer(p) {} 
operator Type*() { return pointer; } 
Type* 
operator->() 

if (pointer == NULL) { 
cerr << “Dereferencing NULL!” << endl; 
pointer = new Type; 

return 
pointer; 

При попытке вызвать оператор 
->
для указателя 
pointer
, равного 
NULL
, в поток 
stderr
выводится 
сообщение об ошибке, после чего создается фиктивный объект и умный указатель переводится на него, 
чтобы программа могла хромать дальше. 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   46   47   48   49   50   51   52   53   ...   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