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



Download 1,95 Mb.
Pdf ko'rish
bet36/144
Sana24.02.2022
Hajmi1,95 Mb.
#223123
TuriРеферат
1   ...   32   33   34   35   36   37   38   39   ...   144
Bog'liq
C -Eldjer-Djeff-for-Real-Programmers-RUS-www.itlibitum.ru

 
49 

// 
Вероятно, здесь следует проверить, что строка 
// 
представляет собой число, принадлежащее к диапазону длинных целых 
return 
atoll(s); 

String s(“1234”); 
long x = s; 
// Вызывается функция operator long() 
Операторы преобразования должны быть функциями класса. Как видно из показанного фрагмента, 
операторы преобразования хороши тем, что компилятор обычно сам может определить, когда они 
должны вызываться. Если ему понадобится длинное целое, он ищет оператор 
long()
. Если ему 
понадобится объект 
Foo
, он ищет в классе 
Foo
либо конструктор с аргументом 
String
, либо 
operator Foo()
. Возникает интересный вопрос: если оператор преобразования делает фактически то 
же, что и конструктор, почему бы не обойтись чем-нибудь одним? Преимущество конструкторов 
состоит в том, что они обеспечивают инкапсуляцию результирующего класса. Чтобы сконструировать 
объект другого класса, оператор преобразования должен очень много знать о нем. Вот почему для 
перехода от одного типа к другому обычно используются конструкторы. А если осуществляется 
переход к базовому типу вроде 
int
? Вряд ли вы будете требовать, чтобы компилятор создавал для 
int
новые конструкторы, которые знают о существовании ваших пользовательских типов. А если и будете, 
то не рискнете признаться в этом вслух. Только оператор преобразования может автоматически 
перейти к базовому типу. Даже если результирующий тип не является базовым, он может быть частью 
готовой библиотеки, которую нежелательно модифицировать. И снова оператор преобразования 
справляется с задачей. 
Операторы преобразования можно объявлять для любых типов данных. Они вызываются без 
аргументов, а тип возвращаемого значения определяется по имени оператора. Операторы 
преобразования, как и все остальные операторы, бывают константными или неконстантными. Часто 
определяется как константная, так и неконстантная версии одного оператора. Как правило, константная 
версия работает более эффективно, поскольку неконстантная версия обычно выполняет копирование 
данных. 
class String { 
private: 
char* 
s; 
public: 
operator const char*() const { return s; } 
operator 
char*(): 
}; 
String::operator char*() 

char* newStr = new char[strlen(s) + 1]; 
strcpy(newStr, 
s); 
return 
newStr; 

Клиентский код, использующий неконстантную версию, должен взять на себя ответственность за 
удаление дубликата. 
Порядок поиска и неоднозначность 
Если во время обработки программы компилятор C++ находит оператор, он выполняет описанные 
ниже действия в указанном порядке, чтобы решить, как его компилировать. Описание относится к 
бинарному оператору, но та же самая логика используется и для унарных операторов: 
1. Если оба аргумента относятся к базовым типам, используется встроенный оператор. 


 50 
2. Если слева указан пользовательский тип, компилятор ищет перепруженный оператор в форме 
функции данного класса, подходящей для всей сигнатуры подвыражения оператора. Если такой 
оператор будет найден, он используется при компиляции. 
3. Если все остальные варианты испробованы, компилятор ищет перегрузку в форме внешней 
функции. 
Неоднозначность может возникнуть лишь в том случае, если она присутствует в левостороннем классе 
или в глобальном пространстве, и никогда — из-за совпадения перегруженных операторов в форме 
функции класса и внешней функции. При наличии неоднозначности сообщение об ошибке выдается 
лишь после вашей попытки реально использовать оператор. Так компилятор внушает ложное чувство 
безопасности и ждет, пока вы утратите бдительность, чтобы огреть вас дубиной по голове. 
Виртуальные операторы 
Операторы классов можно объявлять виртуальными, как и все остальные функции классов. 
Компилятор динамически обрабатывает перегруженный левосторонний оператор, как и любую другую 
функцию класса. Такая возможность особенно полезна в ситуациях, когда вы пытаетесь создать 
семейство классов, но открываете внешнему миру лишь их общий базовый класс. С точки зрения 
синтаксиса все выглядит просто, но логика программы может стать довольно запутанной. Виртуальные 
операторы являются одной из важнейших тем части 3, поэтому сейчас мы не будем вдаваться в 
подробности. 
Оператор -> 
Оператор 
->
занимает особое место среди операторов. Для начала рассмотрим его базовый синтаксис. 
class Pointer { 
private: 
Foo* 
f; 
public: 
Pointer(Foo* foo) : f(foo) {} 
Foo* operator->() const { return f; } 
}; 
Pointer p(new Foo); 
p->MemberOfFoo(); 
В приведенном фрагменте 
р
используется для косвенного вызова функции класса 
Foo
. Компилятор 
интерпретирует любой указатель на структуру или класс (
*
-переменная) как базовый тип 
>
, а для всех 
базовых типов указателей существует встроенный оператор 
->
. Встретив 
->
, компилятор смотрит на 
левостороннее выражение; если оно представляет собой указатель па структуру или указатель на класс, 
для обращения к членам используется встроенный оператор 
->
. Если левостороннее выражение 
представляет собой пользовательский тип, этот тип должен перегрузить оператор 
->
. Перегруженный 
вариант должен возвращать либо указатель на структуру/класс, либо какой-нибудь другой 
пользовательский тип, который также перегружает оператор 
->
. Если возвращаемое значение 
относится к пользовательскому типу, компилятор заменяет левостороннее выражение возвращаемым 
значением оператора 
->
(в нашем примере 
Foo*
) и продолжает свои попытки до тех пор, пока не 
доберется до встроенного указателя. Таким образом, следующее двухшаговое косвенное обращение 
также будет работать. 
class Pointer2 { 
private: 
Pointer 
p; 
public: 
Pointer(Foo* foo) : p(foo) {} 
Pointer operator->() const { return p; } 
}; 
Pointer2 p(new Foo); 
p->MemberOfFoo(); 



Download 1,95 Mb.

Do'stlaringiz bilan baham:
1   ...   32   33   34   35   36   37   38   39   ...   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