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



Download 1,95 Mb.
Pdf ko'rish
bet55/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   51   52   53   54   55   56   57   58   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
87 
сохранить доступ к ним из конструкторов указателя. Теперь клиент никак не сможет добраться до 
Foo

кроме как через 
MP
. Мы еще неоднократно вернемся к вопросу о том, как, когда и где создавать 
указываемые объекты, а пока давайте немного отвлечемся. 
Если конструкторы 
Foo
вызываются с аргументами, существуют две альтернативы: 
1. Вместо того чтобы пользоваться универсальным шаблоном ведущего указателя, создайте для 
Foo
нестандартный класс ведущего указателя 
MPFoo
. Для каждого конструктора 
Foo
создайте 
конструктор 
MPFoo
с точно такой же сигнатурой и передайте его аргументы конструктору 
Foo

2. Воспользуйтесь безаргументным конструктором для создания объекта и предоставьте 
отдельную функцию инициализации, которая может вызываться клиентом после 
конструирования. 
Второй вариант выглядит так: 
class Foo { 
friend class MP
protected: 
Foo(); 
// 
Единственный конструктор 
public: 
Initialized(int, 
char*); 
// 
Оставшаяся часть интерфейса 
}; 
MP mpf; 
mpf->Initialize(17, “Hello”); // Завершить конструирование 
Такое решение выглядит довольно неуклюже, но оно позволяет работать с универсальным шаблоном 
ведущего указателя. Существуют и другие причины для использования инициализирующих функций, о 
которых будет рассказано в следующих главах. Любой из этих вариантов вполне приемлем для 
решения наших текущих задач. 
Уничтожение 
Нет ничего проще: в деструкторе ведущего указателя удаляется и указываемый объект. 
template  
class MP { 
private: 
Type* 
t; 
public: 
~MP() { delete t; } 
}; 
Копирование 
Ой! Опять эти проклятые пользователи... 
MP mpf1;
// Создает Foo, на который ссылается указатель 
MP mpf2 = mpf1; 
// Неудача! 
Пусть знак равенства не вводит вас в заблуждение — здесь происходит конструирование, и эта строка 
эквивалентна строке 
MP mpf2(mpfl)
;. Если не перегрузить конструктор копий и разрешить 
компилятору C++ внести свою лепту, мы получим два ведущих указателя, которые ссылаются на один 
и тот же объект 
Foo
. По умолчанию конструктор копий, генерируемый компилятором, радостно копи-
рует содержащийся в переменной адрес из старого указателя в новый. Проблема решается 
относительно просто. 
template  
class MP { 


 88 
private: 
Type* 
t; 
public: 
MP();
// 
Нормальный 
MP(const MP& mp) : t(*(mp.t)) {} 
// Конструктор копий 
}; 
Этот конструктор копий создает дубликат указываемого объекта, используя для этого конструктор 
копий указываемого объекта. Получается не очень эффективно, но работает. В некоторых ситуациях, с 
которыми мы столкнемся позже, лучше вообще запретить копирование. Проще всего для этого 
объявить конструктор копий закрытым и не назначать ему никаких действий. 
template  
class MP { 
private: 
Type* 
t; 
MP(const MP&) : t(NULL) {} 
// Никогда не будет вызываться 
public: 
MP(); 
}; 
Тем самым мы предотвращаем непреднамеренное копирование в ситуациях вроде следующей: 
void f(MP); 
MP mpf; 
f(mpf);
// 
Создается временная копия 
Для предотвращения копирования также можно воспользоваться дескрипторами, о которых будет 
рассказано ниже. 
Присваивание 
Ааааа! Эти зловредные пользователи когда-нибудь угомонятся?! 
MP mpf1; 
MP mpf2; 
mpf2 = mpf1;
// Нет, только не это... 
В приведенном фрагменте возникают сразу две проблемы. Во-первых, указываемый объект, созданный 
конструктором 
mpf2
, никогда не удаляется. Он превращается в Летучего Голландца, обреченного на 
вечные скитания в океане памяти. Во-вторых, оператор 
=
, используемый компилятором по умолчанию, 
копирует адрес, находящийся в 
t
, из одного указателя в другой, что приводит к появлению двух 
ведущих указателей, ссылающихся на один объект. В исправленном варианте перегруженный оператор 
=
удаляет объект, на который ссылается левосторонний указатель, и заменяет его копией объекта, на 
который ссылается правосторонний указатель. 
template  
class MP { 
private: 
Type* 
t; 
public: 
MP(); // 
Нормальный конструктор 
MP& operator=(const MP& mp) 

if (&mp != this) { 
delete 
t; 
t = new Type(*(mp.t)); 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   51   52   53   54   55   56   57   58   ...   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