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



Download 1,95 Mb.
Pdf ko'rish
bet98/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   94   95   96   97   98   99   100   101   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
173 
}; 
// В файле grandpa.cpp 
class RealGrandpa : public Grandpa { 
// Промежуточный гомоморфный базовый класс 
protected: 
// 
Функции двойной передачи 
}; 
class Dad : public RealGrandpa { ... }; 
class AuntieEm : public RealGrandpa { ... }; 
Наличие производящих функций означает, что производные классы можно скрыть. Добавляя 
промежуточный базовый класс 
RealGrandpa
, мы полностью прячем все жуткие подробности двойной 
передачи в файле .cpp. Никаких защищенных функций в файле .h! 
Нет — конструкторам копий и оператору =! 
Предполагается, что 
Grandpa
— чисто гомоморфный базовый класс, содержащий хотя бы одну чисто 
виртуальную функцию. Это предотвращает непосредственное создание экземпляров 
Grandpa
клиентом. Если вы используете производящую функцию для класса с возможностью создания 
экземпляров, конструкторы следует сделать защищенными, чтобы экземпляры могли создаваться 
только производящей функцией. 
Раз уж мы заговорили на эту тему, после непродолжительных размышлений становится ясно, что 
клиент гомоморфного базового класса не должен использовать конструктор копий или оператор 
=

Если кто-нибудь захочет подублировать экземпляр, создайте специальную версию make-функции для 
копирования 
this

class Grandpa { 
public: 
virtual Grandpa* makeClone() = 0; 
}; 
Эта функция не объявляется статической, поскольку в каждом производном классе она должна решать 
специализированную задачу. С присвоением дело обстоит сложнее. Если переопределить оператор 
=
для левого операнда, непонятно, что же тогда делать с правым операндом, тип которого неизвестен. 
Первое практическое решение — полностью запретить присваивание в таких ситуациях и сделать 
оператор 
=
закрытым. Второе — использовать вариацию на тему двойной передачи: сделать оператор 
=
виртуальным и в каждом производном классе вызывать виртуальную функцию 
AssignTo()

перегружаемую для кажого производного класса. Смотрится уродливо, но работает. 
Объекты классов 
Объектом класса называется объект, предназначенный для создания экземпляров представляемого им 
типа. В нашей терминологии объект класса представляет собой объект, основные функции которого 
являются производящими. Позднее мы возложим на объекты классов и другие обязанности (например, 
описание структуры экземпляра), а пока рассмотрим практический пример. 
class GrandpaClass { 
// Объект класса для Grandpa 
public: 
Grandpa* 
make(); 
// 
Создает экземпляры Grandpa 
}; 
class Grandpa { ... }; 
Все сказанное о производящих функциях относится и к объектам классов, включая спрятанные 
инкапсулированные производные классы, оптимизацию и прозрачность локализации. «Хорошо, — 
скажете вы, — но зачем это нужно?» Во-первых, мы избавляемся от некрасивых статических функций 
и переходим к более чистому, объектно-ориентированному варианту, при котором все происходит 


 174 
посредством отправки сообщений объекту. Во-вторых, мы получаем удобную возможность следить за 
другими характеристиками экземпляров и классов. 
Информация о классе 
В объектах класса удобно хранить сведения о самом классе. Для этого лучше всего создать 
гомоморфный базовый класс для объектов классов. 
class Class { 
protected: 
Collection 
base_classes; 
Collection 
derived_classes; 
String 
class_name; 
Class() 
{}; 
// 
Класс становится абстрактным базовым 
public: 
// 
Функции доступа для получения имени и т.д. 
}; 
Состав хранимой информации в огромной степени зависит от потребностей приложения и от того, 
насколько увлеченно вы занимались SmallTalk на этой неделе. 
Имя класса и создание экземпляров по имени 
Базовая информация, которую может сообщить объект класса, — имя класса в виде некоторой 
символьной строки. Кроме того, можно хранить словарь всех объектов классов, индексируемый по 
имени класса. Если добавить к этому универсальный интерфейс к производящей функции, вам удастся 
реализовать возможность, которая не поддерживается в С++ напрямую — создание экземпляров по 
имени (instantiate by name)
// Где-то в клиентской программе 
Class* c = gClasses.Find(“Grandpa”); 
???* g = (Grandpa*)c->make(???); 
Как видите, практическая польза такого подхода ограничивается некоторыми проблемами. Если мы 
уже знаем, что создается экземпляр 
Grandpa
, то создание экземпляра по имени выглядит неразумно — 
нам будет трудно определить, к какому классу выполняется преобразование. Вдобавок данная схема не 
позволяет предоставить отдельные сигнатуры для производящих функций производных классов. Тем 
не менее, в некоторых ситуациях такая методика оказывается чрезвычайно полезной. Предположим, вы 
сохранили объект в виде потока байтов и теперь загружаете его. Если первые 
n
байт содержит имя 
класса в виде символьной строки, вы сможете найти нужный объект класса для создания экземпляра. 
Как правило, реализация заканчивается созданием во всех классах 
Class
функции 
make(istream&)
или ее эквивалента. Программа приобретает следующий вид: 
// В коде чтения потока 
cin << className; 
Class* c = gClasses.Find(className); 
BasClass* obj = c->make(cin); 
Иерархия классов 
Сведения об иерархии классов можно хранить по разному, но в конечном счете все сводится к 
структурам данных с экземплярами 
Class
. Выше был представлен один из вариантов: вести в каждом 
Class
две коллекции, по одной для базовых и производных классов. Конечно, это следует понимать 
условно — речь идет об иерархии не объектов 
Class
, а представленных ими классов. Необходимость 
различать понятия 
Class
и «класс» наверняка вызовет у вас головную боль, но у поклонников 
SmallTalk и Lisp это считается хорошим развлечением и признаком мастерства. Другой способ — 
ввести одну глобальную структуру данных с парами (базовый, производный), индексируемую в обоих 
направлениях. В некоторых ситуациях вместо пар используются триплеты (базовый, производный, 
порядок), чтобы базовые классы перечислялись в порядке их объявления в соответствующем классе. 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   94   95   96   97   98   99   100   101   ...   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