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



Download 1,95 Mb.
Pdf ko'rish
bet30/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   26   27   28   29   30   31   32   33   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
37 
Компилятор очень сильно обидится на первый конструктор копий — так сильно, что он спустит ваше 
произведение в мусоропровод и даже не сообщит об этом. Для инициализации базового класса и 
переменной будет использован конструктор 
Foo
без аргументов. В 99 случаях из 100 это совсем не то, 
чего вы добивались; обычно требуется, чтобы базовые классы и переменные тоже копировались. 
Вероятно, второй вариант правилен. Базовый класс и переменная присутствуют в списке 
инициализации членов, поэтому будут вызваны их конструкторы копий (компилятор преобразует 
b
к 
типу 
Foo
в выражении 
Foo(b)
). 
В некоторых ситуациях вас интересует именно поведение компилятора по умолчанию. В качестве 
примера рассмотрим следующий базовый класс, который присваивает уникальный серийный номер 
каждому производному объекту. 
class Serialized { 
private: 
static 
int 
NextSerialNumber; 
int 
serialNumber; 
public: 
Serialized(const 
Serialized&); 
Serialized(); 
int 
SerialNumber(); 
}; 
// В Serialized.cpp 
int Serialized::NextSerialNumber = 0; 
Serialized::Serialized() : serialNumber(NextSerialNumber++) 


Serialized::Serialized(const Serialized&) : serialNumber(NextSerialNumber++) 


int Serialized::SerialNumber() 

return 
serialNumber; 

Нac не интересует, какой конструктор — без аргументов или копий — выберет компилятор во время 
компиляции производного класса, поскольку мы перегрузили оба конструктора, и они делают одно и 
то же. 
Закрытые и защищенные конструкторы 
Конструкторы часто объявляются закрытыми и защищенными, чтобы пользователи не могли создавать 
экземпляры класса. Если конструктор объявлен закрытым; только обычные и статические функции 
класса могут создавать стековые экземпляры класса или использовать его в операторе new (по крайней 
мере, с данным конструктором). Если конструктор объявлен защищенным, пользователь может 
создавать экземпляры базового класса, поскольку конструктор базового класса может «вызываться» из 
конструктора производного класса. Пусть для этого потребуется некоторое воображение, но семантика 
именно такова. У этой логики есть один недостаток - она не совсем надежна. Если конструктор 
защищен, любая функция базового или производного класса (включая статические) может создать 
экземпляр базового класса. 
class Foo { 
protected: 
Foo(); 
}; 


 38 
class Bar : public Foo { 
public: 
Foo* 
Fn(); 
}; 
Foo Bar::Fn() 

return 
new 
Foo; 
// 
Работает вопреки всем вашим усилиям 

Возможно, вы полагали, что 
Foo
— абстрактный базовый класс и его экземпляры создать невозможно. 
Оказывается, ничего подобного! В системе защиты открывается зияющая дыра. Друзья классов 
Foo
и 
Bar тоже могут создавать экземпляры 
Foo
. Единственный «железный» способ, который стопроцентно 
гарантирует невозможность создания экземпляров класса — включение в него хотя бы одной чисто 
виртуальной функции. 
Анонимные экземпляры 
Анонимным экземпляром (anonymous instance) называется объект, который... впрочем, сейчас увидите. 
struct Point { 
int 
X; 
int 
Y; 
Point(int x, int y) : X(x), Y(y) {} 
}; 
double distance(Point p) 

return sqrt(double(p.X) * double(p.X) + double(p.Y) * double(p.Y)); 

double d = distance(Point(17, 29)); 
Аргумент функции 
distance()
представляет собой анонимный экземпляр. Мы не создали переменной 
для его хранения. Анонимный экземпляр существует лишь во время вычисления выражения, в котором 
он встречается. 
Анонимные экземпляры обычно связываются с простыми структурами вроде 
Point
, но их можно 
использовать для любого класса. 
Инициализация глобальных объектов 
В спецификации языка порядок конструирования глобальных объектов выглядит довольно сложно. 
Если же учесть причуды коммерческих компиляторов C++, этот порядок становится и вовсе 
непредсказуемым. В соответствии со спецификацией должны вызываться конструкторы глобальных 
объектов, включая конструкторы статических переменных классов и структур, однако многие 
компиляторы этого не делают. Если вам повезло и ваш компилятор считает, что конструкторы важны 
для глобальных переменных, порядок конструирования глобальных объектов зависит от воображения 
разработчика компилятора. Ниже перечислены некоторые правила, которые теоретически должны 
соблюдаться: 
1. Перед выполнением каких-либо операций все глобальные переменные инициализируются 
значением 0. 
2. Объекты, находящиеся в глобальных структурах или массивах, конструируются в порядке их 
появления в структуре или массиве. 
3. Каждый глобальный объект конструируется до его первого использования в программе. 
Компилятор сам решает, следует ли выполнить инициализацию до вызова функции 
main()
или 
отложить ее до первого использования объекта. 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   26   27   28   29   30   31   32   33   ...   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