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



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

 
31 
пропущено в производном классе, компилятор должен интерпретировать версию функции в 
производном классе так, словно она и там была объявлена виртуальной. Я люблю называть подобную 
логику работы компилятора DWIMNIS: «Do what I mean, not what I say» («Делай то, что я 
подразумеваю, а не то, что я говорю»). Как правило, в C++ эта логика начисто отсутствует, поэтому ее 
редкие проявления (как в данном случае) смотрятся неестественно. В следующем примере для обоих 
указателей будет вызвана функция 
Bar::Fn()

class Foo { 
public: 
virtual void Fn(); 
}; 
class Bar { 
public: 
void 
Fn(); // 
Все равно считается виртуальной 
}; 
Bar* b = new Bar; 
b->Fn(); 
// 
Вызывает Bar::Fn() 
Foo* f = b; 
f->Fn(); 
// 
Также вызывает Bar::Fn() 
Подобные ситуации нежелательны по двум причинам. Во-первых, компилятор может неправильно 
интерпретировать их, и тогда в последней строке будет вызвана функция 
Foo::Fn()
. Во-вторых, ваши 
коллеги ни за что не разберутся, почему в одном месте функция 
Fn()
виртуальная, а в другом — нет. 
После бессонной ночи они могут устроить погром в конторе. 
Если в производном классе создается функция с тем же именем, но с другой сигнатурой, она скрывает 
все сигнатуры базового класса для данной функции, но только в области действия производного класса. 
Понятно? Нет? Что ж, вы не одиноки. 
class Foo { 
public: 
virtual void Fn(); 
virtual void Fn(char*); 
}; 
class Bar { 
public: 
virtual void Fn(int); // Можно, но не желательно 
}; 
Вероятно, многие новички-программисты допоздна засиживались на работе, пытаясь разобраться в 
происходящем. А происходит следующее: 
• 
При попытке вызвать 
Fn()
через 
Ваr*
доступной будет лишь одна сигнатура, 
void Fn(int)

Обе версии базового класса скрыты и недоступны через 
Bar*

• 
При преобразовании 
Bar*
в 
Foo*
становятся доступными обе сигнатуры, объявленные в 
Foo

но не сигнатура 
void Fn(int)
. Более того, это не переопределение, поскольку сигнатура 
Bar::Fn()
отличается от версии базового класса. Другими словами, ключевое слово 
virtual
никак не влияет на работу этого фрагмента. 
Если вам когда-нибудь захочется сделать нечто похожее, встаньте с кресла, медленно прогуляйтесь 
вокруг дома, сделайте глубокий вдох, сядьте за компьютер и придумайте что-нибудь другое. Если уж 
перегружать, то перегружайте все сигнатуры функции. Никогда не перегружайте часть сигнатур и 
никогда не добавляйте новые сигнатуры в производный класс без переопределения всех сигнатур 
функции базового класса. Если это покажется слишком сложным, запомните хорошее правило: когда 
при чтении программы возникают вопросы, вероятно, ваше решение неудачное. 


 32 
Друзья 
Любой класс может объявить что-нибудь своим другом (
friend
). Друзья компилируются обычным 
образом, за исключением того, что все защищенные и закрытые члены дружественного класса видны 
так, словно друг является функцией этого класса. Друзьями можно объявлять функции — как 
глобальные, так и члены классов. Классы тоже могут объявляться друзьями других классов; в этом 
случае во всех функциях класса-друга «видны» все члены того класса, другом которого он является. 
class Foo; 
class BarBar { 
public: 
int 
Fn(Foo*); 
}; 
class Foo { 
friend void GlobalFn();
// 
Дружественные глобальные функции 
friend class Bar;
// Дружественный класс 
friend int BarBar::Fn(Foo*); // 
Дружественная функция класса 
friend class DoesNotExist; // См. Ниже 
private: 
int 
x; 
struct 
ListNode 

ListNode* 
next; 
void* 
datum; 
ListNode() : next(NULL), datum(NULL) {} 

head; 
protected: 
int 
y; 
public: 
void 
G(); 
}; 
void GlobalFn() 

Foo* f = new Foo; 
f->x = 17; 
// Разрешается из-за дружеских отношений 

class Bar { 
private: 
Foo* 
f; 
public: 
Bar() : f(new Foo) {} 
void 
WalkList(); 
}; 
void Bar::WalkList() 

Foo::ListNode* n = f->head.next; 
for (; n != NULL; n = n->next) 
cout << n->datum << endl; 

int BarBar::Fn(Foo* f) 

return 
f->x; 




Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   22   23   24   25   26   27   28   29   ...   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