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



Download 1,95 Mb.
Pdf ko'rish
bet105/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   101   102   103   104   105   106   107   108   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
187 
до полного вычисления самого большого вмещающего выражения. Если ваш компилятор следует 
этому правилу, то строку 
{ return *(new Integer(&(value + i.value)); } 
можно записать в виде 
{ return Integer(value + i.value); } 
Аналогично создается и 
PNumber
. Возвращаемое значение будет оставаться действительным внутри 
вычисляемого выражения. Любая ссылка, которая может существовать за пределами вмещающего 
выражения, должна быть получена вызовом функции 
makeClone()
. Эта функция создает 
PNumber
в 
куче или присваивает другой 
Number
виртуальным оператором 
=
для невидимых ведущих указателей, 
о которых говорилось выше. Чтобы ликвидировать эти раздражающие мелкие утечки памяти, можно 
воспользоваться приемами уплотнения и сборки мусора, рассмотренными в части 4. 
Самомодификация и переходимость 
Невидимый ведущий указатель, как и любой умный указатель, может интерпретироваться как 
переходный тип. Если просто заменить указываемый объект каким-нибудь производным классом, вы 
фактически изменяете тип всей видимой клиенту комбинации. На этом основано решение проблемы 
оператора 
+=
, которая требует самомодификации левого операнда, а также возможного оперативного 
изменения типа «на ходу». Если правый операнд 
Complex
складывается с левым операндом 
Integer

тип левого операнда приходится менять. 
// В файле number.h 
class NBase; // Клиентам об этом ничего знать не нужно 
class Number { 
protected: 
Number(const Number&) {} 
Number() 
{} 
public: 
virtual NBase& AddTo(const NBase&) = 0; 
virtual Number& operator+(const Number&) = 0; 
// 
И т.д. 
}; 
// В файле number.cpp 
class Integer; 
class Real; 
class PNumber : public Number { 
private: 
NBase* 
number; 
protected: 
virtual NBase& AddTo(const NBase& n) const 
{ return number->AddTo(n); } 
// #2 
public: 
PNumber(NBase* n) : number(n) {} 
virtual Number& operator+(const Number& n) const 

number = &(n.AddTo(*number)); 
// #1 - замена 
return 
*this; 

}; 
class NBase : public Number { 
// Промежуточный базовый класс 


 188 
// Традиционная двойная передача в NBase 
public: 
virtual NBase& operator+=(const Integer&) const = 0; 
virtual NBase& operator+=(const Real&) const = 0; 
// 
И т.д. 
virtual NBase& AddTo(const NBase&) const = 0; 
virtual Number& operator+(const Number& n) const 
{ return Integer(0); } 
// Заглушка не вызывается 
}; 
class Integer : public NBase { 
private: 
int 
value; 
protected: 
virtual NBase& operator+=(const Integer& i) const 

if (value + i.value достаточно мало) { 
value 
+= 
i.value; 
return 
*this; 

else 

ArbitraryPrecisionInteger 
api(value); 
api 
+= 
i.value; 
delete 
this; 
return 
api; 

public: 
Integer(int i) : value(i) {} 
virtual NBase& AddTo(const NBase& n) const 
{ return n + *this; } 
// 
#3 
}; 
class Real : public NBase { ... }; 
Все как и раньше, разве что операторы 
+
превратились в 
+=
, а двойная передача теперь проходит через 
+=(левый, правый)
и 
AddTo(правый, левый)
, чтобы мы могли различать два порядка аргументов. 
Это важно, поскольку в конечном счете мы хотим заменить указываемый объект левого операнда 
новым. Это происходит в двух местах: 
1. Операторная функция 
PNumber::operator+=(const Number&)
автоматически заменяет 
число полученным новым значением. 
2. Операторная функция 
Integer::operator+=(const Integer&)
возвращает управление, 
если ей не приходится изменять тип; в противном случае после удаления своего объекта она 
возвращает новый объект другого типа. 
По вполне понятным причинам я назову вторую из этих функций заменяющей. Заменяющие функции 
обладают одной экзотической (если не выразиться сильнее) особенностью: нельзя рассчитывать, что 
адрес объекта перед вызовом остается действительным и после вызова. Разумеется, пользоваться этим 
обстоятельством можно лишь в том случае, если эту логику удастся запрятать в самую глубокую и 
темную дыру, чтобы никто в нее не сунулся, но если это удается сделать, хлопотные алгоритмы 
невероятно упрощаются. 
Показанный пример надежно работает, пока 
PNumber
действует как ведущий указатель и пока можно 
гарантировать, что ни один объект, производный от 
NBase
, не будет существовать без ссылающегося 
на него 
PNumber
. В нашем случае, когда все прячется в файле .cpp, дело обстоит именно так. 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   101   102   103   104   105   106   107   108   ...   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