B'ern Straustrap. Spravochnoe rukovodstvo po C++
---------------------------------------------------------------
Vtoroe dopolnennoe izdanie
---------------------------------------------------------------
* SPRAVOCHNOE RUKOVODSTVO
|to spravochnoe rukovodstvo opisyvaet yazyk programmirovaniya S++ po
sostoyanii na maj 1991. S++ - yazyk programmirovaniya obshchego naznacheniya,
baziruyushchijsya na yazyke programmirovaniya S X.
X "The C Programming Language" B. Kernighan, D. Ritchie. Prentice
Hall, 1978, 1988.
Est' russkij perevod: "YAzyk programmirovaniya S. Zadachi po yazyku S"
B. Kernigan, D. Ritchi, A. F'yuer. "Finansy i statistika". 1984
V dopolnenie k vozmozhnostyam S yazyk S++ predostavlyaet klassy, funkcii
podstanovki, peregruzku operacij, peregruzku imen funkcij, postoyannye
tipy, ssylki, operatory upravleniya svobodnoj pamyat'yu, proverku
parametrov funkcij i privedenie tipov. Vse rasshireniya S summiruyutsya
v $$R.18.1. Razlichiya mezhdu S++ i ANSI C++ privedeny v $$R.18.2 X.
X American National Standard X3.159-1989. Amerikanskij nacional'nyj
standart.
Rasshireniya S++ versii 1985 goda do dannogo opisaniya summiruyutsya v
$$R.18.1.2. Razdely, otnosyashchiesya k shablonam tipa ($$R.14) i
upravleniyu osobymi situaciyami ($$R.15), yavlyayutsya mestami planiruemyh
rasshirenij yazyka.
|to rukovodstvo soderzhit sleduyushchee:
1. Vvedenie.
2. Soglasheniya o leksicheskih ponyatiyah.
3. Osnovnye ponyatiya.
4. Standartnye preobrazovaniya.
5. Vyrazheniya.
6. Operatory.
7. Opisaniya.
8. Opisateli.
9. Klassy.
10. Proizvodnye klassy.
11. Kontrol' dostupa k chlenam.
12. Special'nye funkcii-chleny.
13. Peregruzka.
14. SHablony tipov.
15. Upravlenie osobymi situaciyami.
16. Preprocessornaya obrabotka.
Prilozhenie A: Svodka sintaksisa
Prilozhenie B: Sovmestimost'
V zapisi sintaksisa yazyka v etom rukovodstve sintaksicheskie ponyatiya
oboznachayutsya kursivom, a literal'nye slova i simvoly shriftom postoyannoj
shiriny. Varianty perechislyayutsya na otdel'nyh strokah, za isklyucheniem
teh nemnogih sluchaev, kogda dlinnyj spisok variantov daetsya na odnoj
stroke s pometkoj "odin iz". Neobyazatel'nyj terminal'nyj ili
neterminal'nyj simvol oboznachaetsya s pomoshch'yu nizhnego indeksa "opt",
poetomu
{ vyrazhenie opt }
oznachaet neobyazatel'noe vyrazhenie, zaklyuchennoe v figurnye skobki.
R.2 Soglasheniya o leksicheskih ponyatiyah
Programma na S++ sostoit iz odnogo ili neskol'kih fajlov ($$R.3.3).
S logicheskoj tochki zreniya fajl transliruetsya za neskol'ko prohodov.
Pervyj prohod sostoit v preprocessornoj obrabotke ($$R.16), na kotoroj
proishodit vklyuchenie fajlov i makropodstanovka. Rabota preprocessora
upravlyaetsya s pomoshch'yu komand, yavlyayushchihsya strokami, pervyj simvol
kotoryh otlichnyj ot probela est' # ($$R2.1). Rezul'tat raboty
preprocessora est' posledovatel'nost' leksem. Takuyu posledovatel'nost'
leksem, t.e. fajl posle preprocessornoj obrabotki, nazyvayut
edinicej translyacii.
Sushchestvuyut leksemy pyati vidov: identifikatory, sluzhebnye slova,
literaly, operacii i razlichnye razdeliteli. Probely, vertikal'naya
i gorizontal'naya tabulyaciya, konec stroki, perevod stroki i kommentarii
(vse vmeste "obobshchennye" probely), kak ukazano nizhe, ignoriruyutsya,
za isklyucheniem togo, chto oni otdelyayut leksemy. Obobshchennye probely
nuzhny, chtoby razdelit' stoyashchie ryadom identifikatory, sluzhebnye
slova i konstanty.
Esli vhodnoj potok razobran na leksemy do dannogo simvola, to
sleduyushchej leksemoj schitaetsya leksema s maksimal'no vozmozhnoj dlinoj,
kotoraya nachinaetsya s etogo simvola.
Kommentarii
Simvoly /* nachinayut kommentarij, kotoryj zavershaetsya simvolami */.
Takie kommentarii ne mogut byt' vlozhennymi. Simvoly // nachinayut
kommentarij, kotoryj zavershaetsya koncom etoj stroki. Simvoly //,
/* i */ ne imeyut special'nogo naznacheniya v kommentarii // i
rassmatrivayutsya kak obychnye simvoly. Analogichno simvoly // i /*
ne imeyut special'nogo naznacheniya vnutri kommentariya /*.
Identifikator - eto posledovatel'nost' bukv i cifr proizvol'noj dliny.
Pervyj simvol dolzhen byt' bukvoj, simvol podcherkivaniya _ schitaetsya
bukvoj. Propisnye i strochnye bukvy razlichayutsya. Vse simvoly
sushchestvenny.
Perechislennye nizhe identifikatory fiksiruyutsya kak sluzhebnye slova i
v drugom smysle ne mogut ispol'zovat'sya:
asm continue float new signed try
auto default for operator sizeof typedef
break delete friend private static union
case do goto protected struct unsigned
catch double if public switch virtual
char else inline register template void
class enum int return this volatile
const extern long short throw while
V dopolnenie k etomu identifikatory, soderzhashchie dvojnoe podcherkivanie
(__) rezerviruyutsya dlya realizacij S++ i standartnyh bibliotek i
pol'zovateli ne dolzhny upotreblyat' ih.
V predstavlenii programmy na S++ v kodirovke ASCII ispol'zuyutsya
v kachestve operacij ili razdelitelej sleduyushchie simvoly:
! % ^ & * ( ) - + = { } | ~
[ ] \ ; ' : " < > ? , . /
a sleduyushchie kombinacii simvolov ispol'zuyutsya dlya zadaniya operacij:
-> ++ -- .* ->* << >> <= >= == != &&
|| *= /= %= += -= <<= >>= &= ^= |= ::
Kazhdaya operaciya schitaetsya otdel'noj leksemoj.
V dopolnenii k etomu sleduyushchie simvoly rezerviruyutsya dlya preprocessora:
# ##
Opredelennye, zavisyashchie ot realizacii, svojstva, takie kak
tip operacii sizeof ($$R5.3.2) ili diapazony bazovyh tipov
($$R.3.6.1) opredelyayutsya v standartnyh zagolovochnyh fajlah
($$R.16.4)
<float.h> <limits.h> <stddef.h>
|ti fajly yavlyayutsya chast'yu ANSI standarta dlya S. Krome togo
zagolovochnye fajly
<new.h> <stdarg.h> <stdlib.h>
opredelyayut tipy samyh vazhnyh bibliotechnyh funkcij. Dva poslednih
fajla vhodyat v ANSI standart dlya S, fajl <new.h> otnositsya tol'ko
k S++.
Est' neskol'ko vidov literalov (chasto nazyvaemyh "konstantami").
literal:
celaya konstanta
simvol'naya konstanta
konstanta s plavayushchej tochkoj
stroka literalov
Vse celye konstanty, sostoyashchie iz posledovatel'nosti cifr, schitayutsya
desyatichnymi (osnovanie schisleniya desyat'), esli tol'ko oni ne nachinayutsya
s 0 (cifra nol'). Posledovatel'nost' cifr, nachinayushchayasya s 0,
schitaetsya vos'merichnym celym (osnovanie schisleniya vosem'). Cifry 8 i 9
ne yavlyayutsya vos'merichnymi. Posledovatel'nost' cifr, nachinayushchayasya s
0x ili 0X, schitaetsya shestnadcaterichnym celym (osnovanie schisleniya
shestnadcat'). SHestandcaterichnye cifry mogut sostoyat' iz simvolov
ot a ili A do f ili F s desyatichnymi znacheniyami ih ot desyati do
pyatnadcati. Naprimer, chislo dvenadcat' mozhno zapisat' kak 12,
014 ili 0XC.
Tip celoj konstanty opredelyaetsya ee predstavleniem, znacheniem i
okonchaniem. Esli ona desyatichnaya i ne imeet okonchaniya, ee tip budet
pervym podhodyashchim dlya ee znacheniya iz sleduyushchih tipov: int, long int,
unsigned long int. Esli ona vos'merichnaya ili shestnadcaterichnaya i
ne imeet okonchaniya, ee tip budet pervym podhodyashchim dlya ee znacheniya
iz sleduyushchih: int, unsigned int, long int, unsigned long int.
Esli ona okanchivaetsya simvolom u ili U, ee tip budet pervym podhodyashchim
dlya ee znacheniya iz sleduyushchih: unsigned int, unsigned long int. Esli
ona okanchivaetsya simvolom l ili L, ee tip budet pervym podhodyashchim
dlya ee znacheniya iz sleduyushchih: long int, unsigned long int. Esli
ona okanchivaetsya na ul, lu, uL, Lu, Ul, lU, UL ili LU, ee tipom
budet unsigned long int.
R.2.5.2 Simvol'nye konstanty
Simvol'noj konstantoj yavlyaetsya odin ili neskol'ko simvolov, zaklyuchennye
v odinochnye kavychki, naprimer 'x'. Konstanta iz odnogo simvola imeet
tip char. Znachenie konstanty iz odnogo simvola est' poryadkovyj nomer
simvola v tablice kodirovki simvolov na dannoj mashine. Simvol'nye
konstanty iz neskol'kih simvolov imeyut tip int. Znachenie takoj
konstanty zavisit ot realizacii.
Nekotorye simvoly, ne imeyushchie graficheskogo predstavleniya, kak
odinochnaya kavychka ',dvojnaya kavychka ", znak voprosa ?, obratnaya
drobnaya cherta \, mozhno predstavlyat' kombinaciej simvolov (nachinayushchejsya
s \) v sootvetstvii s privodimoj nizhe tablicej:
konec stroki NL (LF) \n
gorizontal'naya tabulyaciya HT \t
vertikal'naya tabulyaciya VT \v
shag nazad BS \b
vozvrat karetki CR \r
perevod formata (avtoregistr) FF \f
signal BEL \a
obratnaya drobnaya cherta \ \\
znak voprosa ? \?
odinochnaya kavychka ' \'
dvojnaya kavychka " \"
vos'merichnoe chislo ooo \ooo
shestnadcaterichnoe chislo hhh \xhhh
Esli za obratnoj drobnoj chertoj sleduet simvol, otlichnyj ot
perechislennyh, rezul'tat neopredelen.
Kombinaciya \ooo sostoit iz obratnoj drobnoj cherty, a kotoroj
sleduyut odna, dve ili tri vos'merichnye cifry. Schitaetsya, chto oni
opredelyayut znachenie iskomogo simvola. Kombinaciya \xhhh sostoit iz
iz obratnoj drobnoj cherty, za kotoroj sleduet x, a za nim, v svoyu
ochered', sleduet posledovatel'nost' shestnadcaterichnyh cifr.
Schitaetsya, chto ona zadaet znachenie iskomogo simvola. Net ogranicheniya
na dlinu etoj posledovatel'nosti shestnadcaterichnyh cifr.
Posledovatel'nost' vos'merichnyh ili shestnadcaterichnyh cifr
okanchivaetsya, kogda vstrechaetsya pervyj simvol, kotoryj ne est'
vos'merichnaya ili shestnadcaterichnaya cifra sootvetstvenno. Esli
znachenie simvol'noj konstanty prevoshodit maksimal'noe iz char,
to ono opredelyaetsya realizaciej.
Simvol'naya konstanta, kotoroj neposredstvenno predshestvuet
bukva L, yavlyaetsya shirokoj simvol'noj konstantoj, naprimer, L'ab'.
Takie konstanty imeyut tip wchar_t, yavlyayushchijsya celochislennym tipom
($$R.3.6.1), opredelennom v standartnom zagolovochnom fajle
<stddef.h>. SHirokie simvoly prednaznacheny dlya takogo nabora
simvolov, gde znachenie simvola ne pomeshchaetsya v odin bajt.
R.2.5.3 Konstanty s plavayushchej tochkoj
Konstanty s plavayushchej tochkoj sostoyat iz celoj chasti, simvola
tochka, drobnoj chasti, e ili E, celogo pokazatelya s vozmozhnym
znakom i vozmozhnym okonchaniem, ukazyvayushchim tip. Celaya i drobnaya
chasti sostoyat iz posledovatel'nosti desyatichnyh (osnovanie
schisleniya desyat') cifr. Ili celaya chast', ili drobnaya chast'
(no ne obe) mogut otsutstvovat'. Ili tochka, ili simvol e (ili E)
vmeste s pokazatelem mogut otsutstvovat' (no ne oba). Tip
konstanty s plavayushchej tochkoj est' double, esli tol'ko on ne
zadan yavno s pomoshch'yu okonchaniya. Okonchaniya f ili F zadayut tip
float, okonchaniya l ili L zadayut tip long double.
Stroka literalov est' posledovatel'nost' simvolov (kak oni opredeleny
v $$R.2.5.2), zaklyuchennaya v dvojnye kavychki, t.e. "...". Stroka
imeet tip "massiv simvolov" i klass pamyati static ($$R.3.5), ona
inicializiruetsya zadannymi simvolami. Budut li vse stroki razlichny
(t.e. hranitsya v otdel'nyh ob容ktah), opredelyaetsya realizaciej.
Sosednie stroki literalov konkateniruyutsya. Simvoly v strokah,
poluchennyh pri konkatenacii, hranyatsya otdel'no. Naprimer, posle
konkatenacii
"\xA" "B"
stroka budet soderzhat' dva simvola '\xA' i 'B' (a ne odin
shestnadcaterichnyj simvol '\xAB').
Posle vseh neobhodimyh konkatenacij k stroke dobavlyaetsya
simvol '\0', chtoby programma, chitayushchaya stroku, mogla opredelit'
ee konec. Razmer stroki raven chislu vseh ee simvolov, vklyuchaya
simvol zavershitel' stroki. Vnutri stroki pered simvolom dvojnoj
kavychki " dolzhen idti simvol \.
Stroka literalov, pered kotoroj neposredstvenno idet simvol L,
schitaetsya shirokosimvol'noj strokoj, naprimer, L"asdf". Takaya
stroka imeet tip "massiv elementov tipa wchar_t", gde wchar_t
celochislennyj tip, opredelennyj v standartnom zagolovochnom fajle
<stddef.h>. Rezul'tat konkatenacii obychnyh i shirokosimvol'nyh
strok literalov neopredelen.
Imya oboznachaet ob容kt, funkciyu, mnozhestvo funkcij, element
perechisleniya, tip, chlen klassa, shablon tipa, znachenie ili metku.
Imya stanovitsya izvestno v programme s pomoshch'yu opisaniya. Imya mozhno
ispol'zovat' tol'ko v predelah chasti programmy, nazyvaemoj oblast'yu
vidimosti imeni. Imya imeet tip, kotoryj zadaet ego ispol'zovanie.
Imya, ispol'zuemoe v bolee chem odnoj edinice translyacii, mozhet
oboznachat' odin i tot zhe (a mozhet i raznye) ob容kt, funkciyu, tip,
shablon tipa ili znachenie, v zavisimosti ot komponovki ($$R.3.3)
etih edinic translyacii.
Ob容kt imeet oblast' dlya ego hraneniya ($$R.3.7). Poimenovannyj
ob容kt imeet klass pamyati ($$R.3.5), kotoryj opredelyaet ego vremya
zhizni. Interpretaciya znachenij, hranyashchihsya v ob容kte, opredelyaetsya
tipom vyrazheniya, zadayushchego dostup k ob容ktu.
R.3.1 Opisaniya i opredeleniya
Opisanie ($$r.7) delaet izvestnym v programme odno ili neskol'ko
imen. Opisanie schitaetsya opredeleniem, esli tol'ko ono ne opisyvaet
funkciyu bez zadaniya ee tela ($$R.8.3), ne soderzhit opisatelya
extern ($$R.7.11), ne imeet chasti inicializacii ili tela funkcii,
ne yavlyaetsya opisaniem staticheskogo chlena dannyh v opisanii klassa
($$R.9.4), ne yavlyaetsya opisaniem imeni klassa ($$R.9.1), ne yavlyaetsya
opisaniem typedef ($$R.7.1.3). Nizhe privedeny primery opredelenij:
int a;
extern const c = 1;
int f(int x) { return x+a; }
struct S { int a; int b; };
enum { up, down };
togda kak nizhe sleduyut tol'ko opisaniya:
extern int a;
extern const c;
int f(int);
struct S;
typedef int Int;
Dlya kazhdogo ob容kta, funkcii, klassa i elementa perechisleniya,
ispol'zuemyh v programme, dolzhno byt' tol'ko odno opredelenie
($$R.3.3). Esli funkciya nikogda ne vyzyvaetsya i ee adres nikogda
ne ispol'zuetsya, ee ne nuzhno opredelyat'. Analogichno, esli imya klassa
ispol'zuetsya tol'ko tak, chto ne trebuetsya znat' opredeleniya klassa,
to takoj klass ne nado opredelyat'.
Sushchestvuet chetyre oblasti vidimosti: lokal'naya, funkciya, fajl i klass.
Lokal'naya: Imya, opisannoe v bloke ($$R.6.3), yavlyaetsya lokal'nym
v etom bloke i mozhet ispol'zovat'sya tol'ko v nem i v blokah,
soderzhashchihsya v etom bloke i poyavlyayushchihsya posle momenta opisaniya.
Imena formal'nyh parametrov rassmatrivayutsya, kak esli by oni byli
opisany v samom ob容mlyushchem bloke etoj funkcii.
Funkciya: Metki ($$R.6.1) mozhno ispol'zovat' povsyudu v funkcii,
v kotoroj oni opisany. Tol'ko metki imeyut oblast' vidimosti,
sovpadayushchuyu s funkciej.
Fajl: Imya opisannoe vne vseh blokov ($$R.6.3) i klassov ($$R.9)
imeet oblast' vidimosti fajl i mozhet byt' ispol'zovano v edinice
translyacii, v kotoroj ono poyavlyaetsya posle momenta opisaniya. Imena,
opisannye s fajlovoj oblast'yu vidimosti, nazyvayutsya global'nymi.
Klass: Imya chlena klassa yavlyaetsya lokal'nym v svoem klasse i
ono mozhet byt' ispol'zovano tol'ko v funkcii-chlene etogo klassa
($$R.9.3), ili posle operacii . , primenyaemoj k ob容ktu dannogo
klassa ($$R.5.2.4) ili ob容ktu proizvodnogo klassa($$R.10),
ili posle operacii ->, primenyaemoj k ukazatelyu na ob容kt dannogo
klassa ($$R.5.2.4) ili na ob容kt proizvodnogo klassa, ili posle
operacii razresheniya :: ($$R.5.1), primenennoj k imeni dannogo
ili proizvodnogo klassa. Imya, vvedennoe s pomoshch'yu operacii
friend ($$R.11.4), prinadlezhit toj zhe oblasti opredelennosti,
chto i klass, soderzhashchij opisanie friend. Klass, vpervye
opisannyj v operatore return ili v tipe parametra, prinadlezhit
k global'noj oblasti vidimosti.
Special'nye soglasheniya dejstvuyut na imena, vvedennye pri opisanii
parametrov funkcii ($$R.8.2.5) i v opisaniyah friend ($$R.11.4).
Imya mozhet byt' skryto yavnym opisaniem togo zhe imeni v ob容mlyushchem
bloke ili klasse. Skrytoe imya chlena klassa vse-taki mozhno
ispol'zovat', esli ono predvaryaetsya imenem klassa, k kotoromu
primenena operaciya :: ($$R.4.1, $$R.9.4, $$R.10). Skrytoe imya ob容kta,
funkcii, tipa ili elementa perechisleniya s fajlovoj oblast'yu vidimosti
mozhno ispol'zovat', esli ono predvaryaetsya unarnoj operaciej ::
($$R.5.1). V dopolnenii k etomu, imya klassa ($$R.9.1) mozhet byt'
skryto imenem ob容kta, funkcii ili elementa perechisleniya, imeyushchego
tu zhe oblast' vidimosti. Esli klass i ob容kt, ili funkciya, ili
element perechisleniya opisany (v lyubom poryadke) s odinakovym imenem
v odnoj oblasti vidimosti, to imya klassa stanovitsya skrytym. Imya
klassa, skrytoe v lokal'noj oblasti vidimosti ili v oblasti
vidimosti klassa imenem ob容kta, funkcii ili elementa perechisleniya,
vse-taki mozhno ispol'zovat', esli predvarit' ego podhodyashchej
specifikaciej class, struct ili union ($$R.7.1.6). Analogichno,
skrytoe imya elementa perechisleniya mozhno ispol'zovat', esli
predvarit' ego specifikaciej tipa enum ($$R.7.1.6). V $$R.10.4
privoditsya svodka pravil oblasti vidimosti.
Momentom opisaniya imeni schitaetsya moment zaversheniya opisatelya imeni
($$R.8), predshestvuyushchej chasti inicializacii (esli ona est').
Naprimer,
int x = 12;
{ int x = x; }
Zdes' vtoroe x inicializiruetsya svoim sobstvennym (neopredelennym)
znacheniem.
Momentom opisaniya elementa perechisleniya schitaetsya moment srazu
posle poyavleniya ego identifikatora, naprimer:
enum { x = x };
Zdes' element perechisleniya x opyat' inicializiruetsya svoim sobstvennym
(neopredelennym) znacheniem.
R.3.3 Programma i svyazyvanie
Programma sostoit iz odnogo ili neskol'kih fajlov, svyazyvaemyh vmeste
($$R.2). Fajl sostoit iz posledovatel'nosti opisanij.
Imya s fajlovoj oblast'yu vidimosti, kotoroe yavno opisano kak
static, yavlyaetsya lokal'nym v svoej edinice translyacii i mozhet
ispol'zovat'sya dlya imenovaniya ob容ktov, funkcij i t.p. v drugih
edinicah translyacii. Govoryat, chto takie imena imeyut vnutrennee
svyazyvanie. Imya s fajlovoj oblast'yu vidimosti, kotoroe yavno opisano
so specifikaciej inline, yavlyaetsya lokal'nym v svoej edinice
translyacii. Imya s fajlovoj oblast'yu vidimosti, kotoroe yavno opisano
so specifikaciej const i ne opisano yavno kak extern, schitaetsya
lokal'nym v svoej edinice translyacii. To zhe verno dlya imeni klassa,
kotoroe ne ispol'zovalos' v nelokal'nyh dlya dannoj edinicy
translyacii opisaniyah ob容kta, funkcii ili klassa, i kotoryj ne
imeet staticheskih chlenov ($$R.9.4), ne imeet funkcij-chlenov, krome
podstanovok ($$R.9.3.2). Vsyakoe opisanie nekotorogo imeni s
fajlovoj oblast'yu vidimosti, kotoroe ne opisano odnim iz perechislennyh
sposobov tak, chtoby imet' vnutrennee svyazyvanie, v mnogofajlovoj
programme oboznachaet odin i tot zhe ob容kt ($$R.3.7), funkciyu
($$R.8.2.5) ili klass ($$R.9). Takie imena nazyvayutsya vneshnimi ili
govoryat, chto oni imeyut vneshnee svyazyvanie. V chastnosti, poskol'ku
nel'zya opisat' imya klassa kak static, vsyakoe upotreblenie imeni
nekotorogo klassa s fajlovoj oblast'yu vidimosti, kotoryj (klass)
ispol'zovalsya dlya opisaniya ob容kta ili funkcii s vneshnim svyazyvaniem,
ili zhe kotoryj imeet staticheskij chlen ili funkciyu-chlen,
ne yavlyayushchuyusya podstanovkoj, budet oboznachat' odin i tot zhe klass.
Imena opredelyaemyh tipov (typedef $$R.7.13), elementy perechisleniya
($$R.7.2) ili imena shablonov tipa ($$R.14) ne imeyut vneshnego
svyazyvaniya.
Staticheskie chleny klassa ($$R.9.4) dopuskayut vneshnee svyazyvanie.
Funkcii-chleny, ne yavlyayushchiesya podstanovkoj, dopuskayut vneshnee
svyazyvanie. Funkcii-chleny, yavlyayushchiesya podstanovkoj, dolzhny imet'
v tochnosti odno opredelenie v programme.
Lokal'nye imena ($$R.3.2), yavno opisannye so specifikaciej
extern, imeyut vneshnee svyazyvanie, esli tol'ko oni uzhe ne byli
opisany kak static ($$R.7.1.1).
Tipy, ispol'zuemye vo vseh opisaniyah nekotorogo vneshnego imeni,
dolzhny sovpadat', za isklyucheniem ispol'zovaniya imen opredelyaemyh
tipov ($$R.7.1.3) i ukazaniya granic massivov ($$R.8.2.4).
Dolzhno byt' v tochnosti odno opredelenie dlya kazhdoj funkcii, ob容kta,
klassa i elementa perechisleniya, ispol'zuemyh v programme. Odnako,
esli funkciya nikogda ne vyzyvaetsya i ee adres nikogda ne ispol'zuetsya,
ee ne nuzhno opredelyat'. Analogichno, esli imya klassa ispol'zuetsya
tol'ko takim obrazom, chto ne trebuetsya znat' opredelenie klassa,
to klass ne nuzhno opredelyat'.
Oblast' vidimosti funkcii mozhet byt' tol'ko fajl ili klass.
S pomoshch'yu specifikacii svyazyvaniya mozhno dobit'sya svyazyvaniya s
opisaniyami na drugom yazyke ($$R.7.4).
R.3.4 Nachalo i okonchanie programmy
Programma dolzhna soderzhat' funkciyu s imenem main(). Ej pripisyvaetsya
rol' nachala programmy. |ta funkciya ne yavlyaetsya predopredelennoj
dlya translyatora, ona ne mozhet byt' peregruzhena, a ee tip zavisit
ot realizacii. Predpolagaetsya, chto lyubaya realizaciya dolzhna
dopuskat' dva privedennyh nizhe opredeleniya i chto mozhno dobavlyat'
posle argv lyubye parametry. Funkciya main mozhet opredelyat'sya tak
int main() { /* ... */ }
ili
int main(int argc, char* argv[]) { /* ... */ }
V poslednem opredelenii argc zadaet chislo parametrov, peredavaemyh
programme okruzheniem, v kotorom ona vypolnyaetsya. Esli argc ne
ravno nulyu, parametry dolzhny peredavat'sya kak stroki, zavershayushchiesya
simvolom '\0', s pomoshch'yu argv[0] do argv[argc-1], prichem
argv[0] dolzhno byt' imenem, pod kotorym programma byla zapushchena,
ili "". Dolzhno garantirovat'sya, chto argv[argc]==0.
Funkciya main() ne dolzhna vyzyvat'sya v programme. Svyazyvanie
main() ($$R.3.3) zavisit ot realizacii. Nel'zya poluchat' adres
main() i ne sleduet opisyvat' ee kak inline ili static.
Vyzov funkcii
void exit(int);
opisannoj v <stdlib.h>, zavershaet programmu. Znachenie parametra
peredaetsya okruzheniyu programmy v kachestve rezul'tata programmy.
Inicializaciya nelokal'nyh staticheskih ob容ktov ($$R.3.5)
edinicy translyacii proishodit prezhde pervogo obrashcheniya k funkcii
ili ob容ktu, opredelennomu v etoj edinice translyacii. |ta
inicializaciya ($$R.8.4, $$R.9.4, &&R.12.1, $$R.12.6.1) mozhet
byt' provedena pered vypolneniem pervogo operatora main() ili
otlozhena do lyubogo momenta, predshestvuyushchego pervomu ispol'zovaniyu
funkcii ili ob容kta, opredelennyh v dannoj edinice translyacii.
Vse staticheskie ob容kty po umolchaniyu inicializiruyutsya nulem ($$R.8.4)
prezhde lyuboj dinamicheskoj (vo vremeni vypolneniya programmy)
inicializacii. Bol'she nikakih trebovanij na poryadok inicializacii
ob容ktov iz razlichnyh edinic translyacii ne nalagaetsya. Inicializaciya
lokal'nyh i staticheskih ob容ktov opisana v $$R.8.4.
Destruktory ($$R.12.4) dlya inicializirovannyh staticheskih
ob容ktov vyzyvayutsya pri vozvrate iz main() ili pri vyzove exit().
Unichtozhenie proishodit v obratnom poryadke po sravneniyu s
inicializaciej. S pomoshch'yu funkcii atexit() iz <stdlib.h> mozhno
ukazat' funkciyu, kotoruyu nuzhno vyzyvat' pri vyhode iz programmy.
Esli bylo obrashchenie k funkcii atexit(), ob容kty, inicializirovannye
do vyzova atexit(), ne dolzhny unichtozhat'sya do teh por, poka ne
proizojdet vyzov funkcii, ukazannoj v atexit(). Esli realizaciya S++
sosushchestvuet s realizaciej S, vse dejstviya, kotorye dolzhny byli
proizojti posle vyzova funkcii, zadannoj v atexit(), proishodyat
tol'ko posle vyzova vseh destruktorov.
Vyzov funkcii
void abort();
opisannoj v <stdlib.h>, zavershaet programmu bez vypolneniya
destruktorov staticheskih ob容ktov i bez vyzova funkcij, zadannyh
v atexit().
Sushchestvuet dva opisyvaemyh klassa pamyati: avtomaticheskij i staticheskij.
Avtomaticheskie ob容kty stanovyatsya lokal'nymi pri peredache
upravleniya v kazhdyj blok.
Staticheskie ob容kty sushchestvuyut i sohranyayut svoe znachenie vo vse
vremya vypolneniya programmy.
Avtomaticheskie ob容kty inicializiruyutsya ($$R.12.1) vsyakij raz,
kogda upravlenie perehodit v blok, gde oni opredeleny i unichtozhayutsya
($$R.12.4) po vyhode iz etogo bloka ($$R.6.7).
Poimenovannyj avtomaticheskij ob容kt ne dolzhen byt' unichtozhen
do okonchaniya ego bloka, tochno tak zhe, kak ne mozhet byt' isklyuchen
poimenovannyj avtomaticheskij ob容kt klassa, imeyushchego konstruktor
ili destruktor s pobochnym effektom, dazhe esli kazhetsya, chto etot
ob容kt ne ispol'zuetsya.
Analogichno, global'nyj ob容kt klassa s konstruktorom ili
destruktorom, imeyushchimi pobochnyj effekt, ne mozhet byt' isklyuchen,
dazhe esli kazhetsya, chto on ne ispol'zuetsya.
Staticheskie ob容kty inicializiruyutsya i unichtozhayutsya v
sootvetstvii s opisaniem v $$R.3.4 i $$R.6.7. S nekotorymi ob容ktami
ne svyazano nikakogo imeni, sm. $$R.5.3.3 i $$R.12.2. Vse global'nye
ob容kty imeyut klass pamyati staticheskij. Lokal'nym ob容ktam i chlenam
klassa mozhno predat' klass pamyati staticheskij s pomoshch'yu yavnogo
ispol'zovaniya specifikacii klassa pamyati static ($$R.7.1.1).
Sushchestvuyut dva vida tipov: osnovnye i proizvodnye.
Sushchestvuet neskol'ko osnovnyh tipov. V standartnom zagolovochnom
fajle <limits.h> zadayutsya v zavisimosti ot realizacii minimal'nye i
maksimal'nye znacheniya kazhdogo tipa.
Ob容kty, opisannye kak simvoly (char), mogut hranit' lyuboj
element iz bazovogo nabora simvolov dannoj mashiny. Esli simvol
etogo nabora hranitsya v simvol'noj peremennoj, to ee znachenie
ravno celomu znacheniyu koda etogo simvola. Simvoly mogut yavno
opisyvat'sya kak unsigned ili signed. Obychnyj char, signed char i
unsigned char yavlyayutsya tremya razlichnymi tipami. Dlya vseh etih
treh tipov trebuetsya odinakovyj ob容m pamyati.
S pomoshch'yu opisanij short int, int i long int mozhno opredelit'
celye treh razlichnyh razmerov. Dlya dlinnyh celyh trebuetsya pamyati
ne men'she chem dlya korotkih celyh, no v realizacii ili korotkie
celye, ili dlinnye celye, ili i te i drugie mogut okazat'sya
ekvivalentnymi obychnym celym. Obychnye celye imeyut razmer,
opredelyaemyj sistemoj komand, razmery drugih celyh opredelyayutsya
konkretnymi potrebnostyami.
Dlya kazhdogo iz tipov signed char, short, int i long sushchestvuet
sootvetstvuyushchij bezznakovyj tip, kotoryj zanimaet tot zhe ob容m
pamyati i udovletvoryaet tem zhe trebovaniyam vyravnivaniya.
Trebovanie vyravnivanie - eto ogranichenie na znachenie ukazatelya
na dannyj ob容kt, kotoroe nakladyvaet realizaciya ($$R.5.4).
Bezznakovye celye, opisannye kak unsigned, podchinyayutsya zakonom
arifmetiki po modulyu 2@n, gde n chislo bitov, ispol'zuemoe dlya
predstavleniya znacheniya. Otsyuda sleduet, chto v arifmetike bezznakovyh
ne voznikaet perepolneniya.
Sushchestvuet tri tipa s plavayushchej tochkoj: float, double i long double.
Tip double garantiruet ne men'shuyu tochnost' predstavleniya, chem
float, a tip long double garantiruet tochnost' ne men'she, chem u
double. Harakteristiki osnovnyh tipov s plavayushchej tochkoj opredelyayutsya
v sootvetstvii s realizaciej v standartnom zagolovochnom fajle
<float.h>.
Tipy char, int lyubyh razmerov i tip perechisleniya ($$R.7.2)
nazyvayutsya celochislennymi tipami. Celochislennye tipy vmeste s
tipami s plavayushchej tochkoj obrazuyut arifmeticheskie tipy.
Tip void zadaet pustoe mnozhestvo znachenij. On ispol'zuetsya dlya
oboznacheniya tipa funkcij, kotorye ne vozvrashchayut rezul'tat. Nel'zya
opisyvat' ob容kty s tipom void. Lyuboe vyrazhenie mozhno yavno
preobrazovat' k tipu void ($$R.5.4), poluchivsheesya vyrazhenie mozhno
ispol'zovat' tol'ko kak vyrazhenie-operator ($$R.6.2), kak
levyj operand operacii zapyataya ($$R.5.18) ili v kachestve vtorogo ili
tret'ego operanda v operacii ?: ($$R.5.16).
Sushchestvuet potencial'no beskonechnoe chislo proizvodnyh tipov, kotorye
stroyatsya iz osnovnyh tipov sleduyushchimi sposobami:
massiv ob容ktov dannogo tipa, $$R.8.4;
funkcii, imeyushchie parametry dannogo tipa i vozvrashchayushchie ob容kty
dannogo tipa, $$R.8.2.5;
ukazateli na ob容kty ili funkcii dannogo tipa, $$R.8.2.1;
ssylki na ob容kty ili funkcii dannogo tipa, $$R.8.2.2;
konstanty, yavlyayushchiesya znacheniyami dannogo tipa, $$R.7.1.6;
klassy, soderzhashchie sovokupnost' ob容ktov razlichnyh tipov ($$R.9),
nabor funkcij dlya upravleniya etimi ob容ktami ($$R.9.3) i
i spisok ogranichenij na dostup k etim ob容ktam i funkciyam, $$R.11;
struktury, kotorye yavlyayutsya klassami bez standartnyh ogranichenij
na dostup, $$r.11;
ob容dineniya, kotorye yavlyayutsya strukturami, sposobnymi soderzhat'
v raznoe vremya ob容kty razlichnyh tipov, $$R.9.5;
ukazateli na chleny klassov, kotorye zadayut chleny dannogo tipa
sredi vseh ob容ktov dannogo klassa, $$R.8.2.3.
V obshchem sluchae ukazannye metody postroeniya ob容ktov mogut primenyat'sya
rekursivno, ogranicheniya privedeny v $$r.8.2.1, $$R.8.2.4, $$R.8.2.5
i $$R.8.2.2.
Pro ukazatel' na ob容kty tipa T govoryat "ukazatel' na na T". Naprimer,
pro ukazatel' na ob容kt tipa int govoryat "ukazatel' na int", a
ukazatel' na ob容kt klassa X nazyvaetsya "ukazatel' na X".
Ob容kty tipa void* (ukazatel' na void), const void* i
volatile void* mogut ispol'zovat'sya kak ukazateli na ob容kty
neizvestnogo tipa. Ob容kt tipa void* dolzhen imet' dostatochno pamyati,
chtoby hranit' ukazatel' na lyuboj ob容kt.
Vse fragmenty rukovodstva, govoryashchie ob "ukazatelyah", ne otnosyatsya
k ukazatelyam na chleny, za isklyucheniem ukazatelej na staticheskie
chleny.
Osnovnye i proizvodnye tipy mozhno poimenovat' s pomoshch'yu mehanizma
typedef ($$R.7.1.3), a semejstvo tipov i funkcij mozhno zadat' i
poimenovat' s pomoshch'yu mehanizma shablona tipov ($$R.14).
Lyuboj ob容kt - eto nekotoraya oblast' pamyati, adres - vyrazhenie,
ssylayushcheesya na ob容kt ili funkciyu. Ochevidnym primerom adresa budet
imya ob容kta. Sushchestvuyut operacii, porozhdayushchie adresa, naprimer,
esli E vyrazhenie tipa ukazatel', to *E - adresnoe vyrazhenie,
sootvetstvuyushchee ob容ktu, na kotoryj ukazyvaet E. Termin "adres"
("lvalue" t.e. left value - levaya velichina) poyavlyaetsya iz operatora
prisvaivaniya E1 = E2, gde levyj operand E1 dolzhen "adresovat'"
izmenyaemuyu peremennuyu. Pri obsuzhdenii vseh operacij v $$R.5 ukazyvaetsya
primenimy li oni k adresnym operandam i porozhdayut li oni sami adresa.
Adres mozhet izmenyat'sya, esli on ne yavlyaetsya imenem funkcii,
imenem massiva ili const.
R.4 Standartnye preobrazovaniya
Nekotorye operacii v zavisimosti ot svoih operandov mogut vyzvat'
preobrazovanie znacheniya operanda ot odnogo tipa k drugomu. Zdes'
opisyvayutsya preobrazovaniya, vyzvannye samymi obychnymi operaciyami,
i ob座asnyaetsya kakovy mogut byt' rezul'taty takih preobrazovanij.
Po mere nadobnosti budut dany dopolnitel'nye ob座asneniya pri
obsuzhdenii kazhdoj operacii. Podobnye preobrazovaniya takzhe proishodyat
pri inicializacii ($$R.8.4, $$R.8.4.3, $$R.12.8, $$R.12.1).
V $$R.12.3 i $$R.13.2 opisyvayutsya preobrazovaniya, zadannye
pol'zovatelem, i ih sootnosheniya so standartnymi preobrazovaniyami.
V rezul'tate preobrazovaniya mozhet poluchit'sya adres, tol'ko esli
rezul'tat est' ssylka ($$R.8.2.2).
R.4.1 Standartnye preobrazovaniya dlya celochislennyh
Vsyudu, gde trebuetsya celoe, mozhno ispol'zovat' char, short int,
element perechisleniya ($$R.7.2) ili bitovoe pole ($$R.9.6), prichem
v znakovom i bezznakovom variantah. Esli int mozhet predstavlyat'
vse znacheniya ishodnogo tipa, znachenie preobrazuetsya k int, inache
ono preobrazuetsya k unsigned int. |to nazyvaetsya standartnym
preobrazovaniem dlya celochislennyh.
R.4.2 Preobrazovaniya celochislennyh
Esli celoe preobrazuetsya v bezznakovyj tip, to poluchennoe znachenie
est' naimen'shee bezznakovoe celoe, sovpadayushchee s celym so znakom
po (mod 2**n), gde n est' chislo bitov v predstavlenii bezznakovogo
celogo. Dlya predstavleniya v dopolnitel'nom kode eto preobrazovanie
lish' konceptual'noe, nikakih izmenenij v dvoichnom predstavlenii
v dejstvitel'nosti ne proishodit.\
Esli celoe preobrazuetsya k znakovomu tipu, znachenie ne menyaetsya,
pri uslovii, chto ego mozhno predstavit' s pomoshch'yu novogo tipa,
inache znachenie opredelyaetsya realizaciej.
R.4.3 Znacheniya s plavayushchej tochkoj i dvojnoj tochnost'yu
Dlya vyrazhenij tipa float mozhet ispol'zovat'sya arifmetika s obychnoj
tochnost'yu. Esli znachenie s plavayushchej tochkoj men'shej tochnosti
preobrazuetsya v znachenie tipa float ravnoj ili bol'shej tochnosti,
to izmeneniya znacheniya ne proishodit. Esli znachenie s plavayushchej
tochkoj bol'shej tochnosti preobrazuetsya v znachenie tipa float
men'shej tochnosti i znachenie nahoditsya v predelah, zadavaemyh
predstavleniem tipa, to v rezul'tate mozhet poluchit'sya ili
blizhajshee bol'shee ili blizhajshee men'shee predstavimoe znachenie.
Esli rezul'tat okazalsya vne granic predstavleniya tipa, povedenie
neopredeleno.
R.4.4 Celochislennye i chisla s plavayushchej tochkoj
Preobrazovanie znacheniya s plavayushchej tochkoj k celochislennomu tipu
svoditsya k "usecheniyu", t.e. otbrasyvaniyu drobnoj chasti. Takie
preobrazovaniya zavisyat ot mashiny, v chastnosti v kakuyu storonu budet
prohodit' usechenie dlya otricatel'nyh chisel opredelyaetsya na raznyh
mashinah po raznomu. Rezul'tat schitaetsya neopredelennym, esli
znachenie nel'zya predstavit' v celochislennom tipe.
Preobrazovaniya celochislennyh znachenij k znacheniyam s plavayushchej
tochkoj matematicheski korrektny nastol'ko, naskol'ko eto pozvolyaet
sistema komand. Mozhet proizojti poterya tochnosti, esli celochislennoe
znachenie nel'zya tochno predstavit' kak znachenie s plavayushchej tochkoj.
R.4.5 Arifmeticheskie preobrazovaniya
Dlya bol'shinstva operacij preobrazovaniya operandov i tip rezul'tata
opredelyayutsya odnimi i i temi zhe pravilami. |to pravilo mozhno nazvat'
"obychnymi arifmeticheskimi preobrazovaniyami".
Esli odin iz operandov est' long double, drugoj operand
preobrazuetsya v long double.
Inache, esli odin iz operandov est' double, drugoj operand
preobrazuetsya v double.
Inache, esli odin iz operandov est' float, drugoj operand
preobrazuetsya v float.
Inache, esli standartnye celochislennye preobrazovaniya ($$R.4.1)
proishodyat nad oboimi operandami.
Togda, esli odin iz operandov est' unsigned long, drugoj
operand preobrazuetsya v unsigned long.
Inache, esli odin iz operandov est' long int, a drugoj -
unsigned int, to pri uslovii, chto long int mozhet predstavlyat'
vse vozmozhnye znacheniya unsigned int, znachenie unsigned int
preobrazuetsya v long int, v protivnom sluchae oba operanda
preobrazuyutsya v unsigned long int.
Inache, esli odin iz operandov est' long, drugoj operand
preobrazuetsya v long.
Inache, esli odin iz operandov est' unsigned, drugoj operand
preobrazuetsya v unsigned.
Inache, oba operanda dolzhny byt' int.
R.4.6 Preobrazovaniya ukazatelej
Vsyudu, gde ukazateli ($$R.8.2.1) prisvaivayutsya, inicializiruyutsya,
sravnivayutsya ili ispol'zuyutsya inym obrazom, mogut proishodit'
sleduyushchie preobrazovaniya:
Konstantnoe vyrazhenie ($$R.5.19), kotoroe svoditsya k nulyu,
preobrazuetsya v ukazatel', obychno nazyvaemyj pustym ukazatelem.
Garantiruetsya, chto znachenie takogo ukazatelya budet otlichno ot
lyubogo ukazatelya na ob容kt ili funkciyu.
Ukazatel' na ob容kt lyubogo tipa, ne yavlyayushchegosya const ili
volatile, mozhno preobrazovat' v void*.
Ukazatel' na funkciyu mozhno preobrazovat' v void*, pri uslovii,
chto dlya void* otvoditsya dostatochno pamyati, chtoby hranit' etot
ukazatel'.
Ukazatel' na dannyj klass mozhno preobrazovat' v ukazatel' na
dostupnyj bazovyj klass dannogo klassa ($$R.10), esli takoe
preobrazovanie ne soderzhit dvusmyslennost' ($$R.10.1). Bazovyj
klass schitaetsya dostupnym, esli dostupny ego obshchie chleny ($$R.11.1).
Rezul'tatom preobrazovaniya budet ukazatel' na ob容kt tipa bazovogo
klassa, vlozhennyj v ob容kt tipa proizvodnogo klassa. Pustoj ukazatel'
(0) preobrazuetsya sam v sebya.
Vyrazhenie tipa "massiv T" mozhet preobrazovyvat'sya v ukazatel'
na nachal'nyj element massiva.
Vyrazhenie tipa "funkciya, vozvrashchayushchaya T" preobrazuetsya v "ukazatel'
na funkciyu, vozvrashchayushchuyu T", za isklyucheniem teh sluchaev, kogda
ono ispol'zuetsya kak operand adresnoj operacii & ili operacii
vyzova funkcii ().
R.4.7 Preobrazovaniya ssylok
Vsyudu, gde ssylki ($$R.8.2.2) inicializiruyutsya (vklyuchaya peredachu
parametrov ($$R.5.2.2) i vozvrat znacheniya funkcii ($$R.6.6.3)) ili
ispol'zuyutsya inym obrazom, vozmozhny sleduyushchie preobrazovaniya:
Ssylka na dannyj klass mozhet byt' preobrazovana v ssylku na dostupnyj
bazovyj klass ($$R.10, $$R.11.1) dannogo klassa ($$R.8.4.3),
pri uslovii, chto takoe preobrazovanie ne soderzhit dvusmyslennosti
($$R.10.1.1). Rezul'tatom preobrazovaniya budet ssylka na ob容kt
bazovogo klassa, vlozhennyj v ob容kt proizvodnogo klassa.
R.4.8 Ukazateli na chleny
Vsyudu, gde ukazateli na chleny ($$R.8.2.3) inicializiruyutsya,
prisvaivayutsya, sravnivayutsya ili ispol'zuyutsya inym obrazom,
mogut proishodit' sleduyushchie preobrazovaniya:
Konstantnoe vyrazhenie ($$R.5.19), kotoroe svoditsya k nulyu,
preobrazuetsya v ukazatel' na chlen. Garantiruetsya, chto ego
znachenie budet otlichno ot lyubyh drugih ukazatelej na chleny.
Ukazatel' na chlen dannogo klassa mozhno preobrazovat' v
ukazatel' na chlen proizvodnogo ot dannogo klassa, pri uslovii,
chto dopustimo obratnoe preobrazovanie ot ukazatelya na chlen proizvodnogo
klassa v ukazatel' chlen bazovogo klassa, i chto ono vypolnimo
odnoznachnym obrazom ($$R.10.1.1).
Pravilo preobrazovaniya ukazatelej na chleny (t.e. ot ukazatelya na
chlen bazovogo klassa k ukazatelyu na chlen proizvodnogo klassa) vyglyadit
perevernutym, esli sravnivat' ego s pravilom dlya ukazatelej na
ob容kty (t.e. ot ukazatelya na proizvodnyj ob容kt k ukazatelyu na
bazovyj ob容kt) ($$R.4.6, $$R.10). |to neobhodimo dlya garantii
nadezhnosti tipov.
Otmetim, chto ukazatel' na chlen ne yavlyaetsya ukazatelem na ob容kt
ili ukazatelem na funkciyu i pravila preobrazovanij takih ukazatelej
ne primenimy dlya ukazatelej na chleny. V chastnosti ukazatel' na chlen
nel'zya preobrazovat' v void*.
Zdes' opredelyayutsya sintaksis, poryadok vychisleniya i naznachenie
vyrazhenij. Vyrazhenie - eto posledovatel'nost' operacij i operandov,
kotoraya zadaet vychislenie. Vychislenie mozhet vydavat' v kachestve
rezul'tata znachenie i mozhet vyzyvat' pobochnye effekty.
Operacii mogut byt' peregruzheny, t.e. im mozhet byt' pripisano znachenie,
kogda oni primenyayutsya k vyrazheniyam tipa klass ($$R.9). Primenenie
peregruzhennyh operacij preobrazuetsya v vyzovy funkcij v sootvetstvii
s opisaniem v $$R.13.4. Peregruzhennye operacii podchinyayutsya
sintaksicheskim pravilam, opredelennym v etom razdele, no trebovaniya
k tipu operanda, adresu i poryadku vychisleniya zamenyayutsya na pravila
vyzova funkcii. Sootnosheniya mezhdu operaciyami, tipa ++a oznachaet
a+=1, ne garantiruyutsya dlya peregruzhennyh operacij ($$R.13.4).
V etom razdele opisano primenenie operacij k tipam, dlya kotoryh
oni ne yavlyayutsya peregruzhennymi. Peregruzka operacij ne mozhet izmenit'
pravila primeneniya operacij k tipam, dlya kotoryh takoe primenenie
predusmotreno v samom yazyke.
Poryadok vychisleniya podvyrazhenij opredelyaetsya prioritetom i poryadkom
primeneniya operacij. Obychnye matematicheskie pravila associativnosti
i kommutativnosti operacij dejstvuyut tol'ko, esli operacii
dejstvitel'no associativny ili kommutativny. Za isklyucheniem
ogovorennyh sluchaev poryadok vychisleniya operandov konkretnoj operacii
neopredelen. V chastnosti, esli v vyrazhenii znachenie izmenyaetsya
dvazhdy, rezul'tat vyrazheniya neopredelen, esli tol'ko poryadok
vypolneniya ne obespechivaetsya samimi operaciyami, naprimer:
i = v[i++]; // the value of `i' is undefined
i=7,i++,i++; // `i' becomes 9
Reakciya na perepolnenie i delenie na nul' pri vychislenii vyrazheniya
zavisit ot realizacii. V bol'shinstve sushchestvuyushchih realizacij S++
ignoriruetsya perepolnenie celyh. Reakciya na delenie na nul' i
oshibki operacij nad chislami s plavayushchej tochkoj var'iruetsya ot
mashiny k mashine i obychno svyazana s sootvetstvuyushchimi bibliotechnymi
funkciyami.
Krome ogovorennyh sluchaev, operandy tipa const T, volatile T,
T&, const T& i volatile T& mozhno ispol'zovat', kak esli by oni
imeli tip prosto T. Analogichno, operandy tipa T* const, T*volatile
mozhno ispol'zovat', kak esli by oni imeli tip prosto T*, za
isklyucheniem ogovorennyh sluchaev. Analogichno, prosto tip T mozhno
ispol'zovat' vsyudu, gde trebuetsya tip volatile T ili const T.
|ti pravila mozhet primenyat' v kombinacii, tak chto const T* volatile
mozhno ispol'zovat' tam, gde trebuetsya T*, za isklyucheniem ogovorennyh
sluchaev. Pri rassmotrenii razresheniya peregruzki ($$R.13.2) takoe
ispol'zovanie operacij ne schitaetsya standartnym preobrazovaniem
operandov.
Esli vyrazhenie imeet tip "ssylka na T" ($$R.8.2.2, $$R.8.4.3),
znachenie vyrazhenie est' ob容kt tipa "T", na kotoryj nastroena
ssylka. Vyrazhenie yavlyaetsya adresom. Ssylku mozhno predstavlyat' kak
imya ob容kta.
Dopustimy opredelennye pol'zovatelem preobrazovaniya ob容ktov
klassa v (i obratno) osnovnye tipy, ukazateli i t.d. ($$R.12.3)
Esli oni nedvusmyslenny ($$R.13.2), takie preobrazovaniya mogut
primenyat'sya translyatorom vsegda, kogda poyavlyaetsya ob容kt tipa klassa
v kachestve operanda operacii, v kachestve inicializiruyushchego
vyrazheniya ($$R.8.4), v kachestve vyrazheniya, zadayushchego uslovie ($$R.6.4),
ili v kachestve vyrazheniya, ispol'zuemogo v operatore cikla ($$R.6.5),
ili v kachestve znacheniya, vozvrashchaemogo funkciej ($$R.6.6.3),
ili v kachestve parametra funkcii ($$R.5.2.2).
R.5.1 Pervichnye vyrazheniya
Pervichnymi vyrazheniyami yavlyayutsya literaly, imena i imena, opredelennye
s pomoshch'yu operacii razresheniya oblasti vidimosti ::.
pervichnoe-vyrazhenie:
literal
this
:: identifikator
:: imya-funkcii-operacii
:: utochnennoe-imya
( vyrazhenie )
imya
Literal yavlyaetsya pervichnym vyrazheniem. Ego tip opredelyaetsya
ego vidom ($$R.2.5).
V tele nestaticheskoj funkcii-chlene ($$R.9.3) sluzhebnoe slovo
this oboznachaet ukazatel' na ob容kt, k kotoromu otnositsya vyzov
funkcii. Sluzhebnoe slovo this nel'zya ispol'zovat' vne tela
funkcii-chlena klassa.
Operaciya :: , za kotoroj sleduet identifikator ili
imya-operacii-funkcii ili utochnennoe-imya yavlyayutsya pervichnym
vyrazheniem. Ego tip zadaetsya opisaniem identifikatora, imeni
ili imeni-funkcii-operacii. Rezul'tatom yavlyaetsya identifikator,
imya ili imya-funkcii-operacii. Rezul'tat yavlyaetsya adresom, esli
identifikator yavlyaetsya adresom. Identifikator ili imya-funkcii-operacii
dolzhny imet' fajlovuyu oblast' vidimosti. S pomoshch'yu operacii ::
mozhno obrashchat'sya k tipu, ob容ktu, funkcii ili elementu perechisleniya,
dazhe esli oboznachayushchij ih identifikator yavlyaetsya skrytym ($$R.3.2).
Vyrazhenie v skobkah yavlyaetsya pervichnym vyrazheniem, tip i znachenie
kotorogo identichny im zhe u vyrazheniya bez skobok. Nalichie skobok
ne vliyaet na to, yavlyaetsya vyrazhenie adresom ili net.
Ponyatie imya - eto opredelennoe pervichnoe-vyrazhenie, kotoroe
mozhet poyavlyat'sya tol'ko posle . i -> ($$R.5.2.4):
imya:
identifikator
imya-funkcii-operacii
imya-funkcii-preobrazovaniya
~imya-klassa
utochnennoe-imya
Identifikator est' imya, pri uslovii chto on opisan nadlezhashchim obrazom
($$R.7). Ponyatie imya-funkcii-operacii opisano v ($$R.13.4), a
ponyatie imya-funkcii-preobrazovaniya v ($$R.12.3.2). Konstrukciya
~imya-klassa oboznachaet destruktor ($$R.12.4).
utochnennoe-imya:
utochnyayushchee-imya-klassa :: imya
Ponyatie utochnyayushchee-imya-klassa, za kotorym sleduet :: i imya chlena
etogo klassa ($$R.9.2), ili chlena bazovogo po otnosheniyu k dannomu
klassa ($$R.10) yavlyaetsya utochnennoe-imya. Ego tip est'
tip chlena, a rezul'tat vyrazheniya est' etot chlen. Rezul'tat yavlyaetsya
adresom, esli takovym yavlyaetsya chlen. Imya klassa mozhet byt' skryto
drugim imenem (ne tipa), v takom sluchae vse ravno imya klassa
dostupno i ego mozhno ispol'zovat'. Esli ispol'zuetsya
imya-klassa::imya-klassa ili imya-klassa::~imya-klassa, oba ponyatiya
imya-klassa dolzhny oboznachat' odin i tot zhe klass. S pomoshch'yu takoj
zapisi oboznachayutsya konstruktory ($$R.12.1) i destruktory ($$R.12.4)
sootvetstvenno. Mozhno ispol'zovat' utochnyayushchie imena
neodnokratno, naprimer, N1::N2::N3::n, chtoby oboznachat' vlozhennye
tipy ($$R.9.7).
R.5.2 Postfiksnye vyrazheniya
Postfiksnye vyrazheniya primenyayutsya sleva napravo.
postfiksnoe-vyrazhenie:
pervichnoe-vyrazhenie
postfiksnoe-vyrazhenie [ vyrazhenie ]
postfiksnoe-vyrazhenie ( spisok-vyrazhenij opt )
imya-prostogo-tipa ( spisok-vyrazhenij opt )
postfiksnoe-vyrazhenie . imya
postfiksnoe-vyrazhenie -> imya
postfiksnoe-vyrazhenie ++
postfiksnoe-vyrazhenie --
spisok-vyrazhenij:
vyrazhenie-prisvaivaniya
spisok-vyrazhenij , vyrazhenie-prisvaivaniya
Postfiksnoe vyrazhenie, za kotorym sleduet vyrazhenie v kvadratnyh
skobkah, yavlyaetsya postfiksnym vyrazheniem. Intuitivnyj smysl ego
indeksirovanie. Pervoe iz vyrazhenij dolzhno imet' tip "ukazatel' na T",
a vtoroe byt' celochislennogo tipa. Tip rezul'tata est' "T". Vyrazhenie
E1[E2] sovpadaet (po opredeleniyu) s vyrazheniem *((E1) + (E2)).
Podrobnosti operacij * i + dany v $$R.5.3 i $$R.5.7, a massivy
obsuzhdayutsya v $$R.8.2.4.
Vyzov funkcii yavlyaetsya postfiksnym vyrazheniem, za kotorym sleduet,
vozmozhno pustoj, spisok vyrazhenij v skobkah, razdelennyh zapyatoj.
|ti vyrazheniya obrazuyut fakticheskie parametry funkcii. Postfiksnoe
vyrazhenie dolzhno imet' tip "funkciya, vozvrashchayushchaya T", "ukazatel' na
funkciyu, vozvrashchayushchuyu T" ili "ssylka na funkciyu, vozvrashchayushchuyu T",
a rezul'tat operacii vyzova imeet tip "T".
Pri vyzove funkcii proishodit inicializaciya kazhdogo formal'nogo
parametra ($$R.8.4.3, $$R.12.8, $$r.12.1) fakticheskim parametrom.
Proizvodyatsya standartnye ($$R.4) i zadannye pol'zovatelem ($$R.12.3)
preobrazovaniya tipa. V funkcii mozhet izmenyat'sya znacheniya nepostoyannyh
formal'nyh parametrov, no eti izmeneniya ne mogut povliyat' na znacheniya
fakticheskih parametrov, krome togo sluchaya, kogda formal'nyj parametr
imeet tip ssylki bez specifikacii const ($$R.8.2.2). Esli formal'nyj
parametr imeet tip ssylki pri neobhodimosti mozhet sozdavat'sya
vremennaya peremennaya ($$R.7.1.6, $$R.2.5,$$R.2.5.4,$$R.8.2.4,
$$R.12.2). Dobavim, chto vozmozhno izmenenie nepostoyannyh ob容ktov s
pomoshch'yu parametrov-ukazatelej.
Funkciyu mozhno opisat' takim obrazom, chto ona smozhet ispol'zovat'
men'shee chislo parametrov (opredeliv parametry po umolchaniyu $$R.8.2.6)
ili bol'shee chislo parametrov (s pomoshch'yu ellipsisa ... $$R.8.2.5),
chem bylo ukazano pri opredelenii funkcii ($$R.8.3).
Funkciyu mozhno vyzvat' tol'ko, esli opisanie ee dostupno v toj oblasti
vidimosti, gde proishodit vyzov. Otsyuda sleduet, vsyakij formal'nyj
parametr, sootvetstvuyushchij nekotoromu fakticheskomu parametru, dolzhen
byt' dostupen, esli ne schitat' ellipsis (...).
Pered vyzovom vsyakij fakticheskij parametr tipa float, dlya kotorogo
net formal'nogo parametra, preobrazuetsya k tipu double, a tipa
char, short, perechisleniya ili bitovoe pole, dlya kotorogo net
formal'nogo parametra, preobrazuetsya k tipu int ili unsigned
soglasno standartnym preobrazovaniyam celochislennyh ($$R.4.1).
Ob容kt, yavlyayushchijsya klassom i ne imeyushchij opisaniya formal'nogo parametra,
peredaetsya pri vyzove kak struktura dannyh.
Ob容kt, yavlyayushchijsya klassom i imeyushchij opisanie formal'nogo
parametra peredaetsya s pomoshch'yu inicializacii formal'nogo parametra
fakticheskim parametrom, kotoraya proishodit pered vypolneniem
funkcii posredstvom vyzova konstruktora ($$R.12.2, $$R.12.8).
Poryadok vychislenij parametrov neopredelen i uchtite, chto on
mozhet byt' razlichen u raznyh translyatorov. Vse pobochnye effekty
vyrazhenij fakticheskih parametrov mogut proishodit' pered nachalom
vypolneniya funkcii. Poryadok vychisleniya postfiksnyh vyrazhenij i
spiska vyrazhenij parametrov neopredelen.
Dopustimy rekursivnye vyzovy.
Operaciya vyzova funkcii porozhdaet adres tol'ko, esli tip
rezul'tata est' adres.
R.5.2.3 YAvnye preobrazovaniya tipa
Konstrukciya imya-prostogo-tipa ($$R.7.1.6), za kotoroj sleduet
spisok-vyrazhenij v skobkah obrazuet znachenie ukazannogo tipa
s uchetom spiska vyrazhenij. Esli spisok vyrazhenij soderzhit bolee
odnogo znacheniya, tip dolzhen byt' klassom s konstruktorom, opisannym
sootvetstvuyushchim obrazom ($$R.8.4, $$R.12.1).
Konstrukciya imya-prostogo-tipa ($$R.7.1.6), za kotoroj sleduet
para skobok (pustaya), obrazuet znachenie ukazannogo tipa. Esli tip
yavlyaetsya klassom s konstruktorom, opisannym sootvetstvuyushchim obrazom,
budet vyzvan etot konstruktor, v protivnom sluchae rezul'tatom
budet neopredelennoe znachenie ukazannogo tipa, sm. tak zhe ($$R.5.4).
R.5.2.4 Dostup k chlenu klassa
Postfiksnoe vyrazhenie, za kotorym sleduet tochka (.) i imya, yavlyaetsya
postfiksnym vyrazheniem. Pervoe vyrazhenie dolzhno byt' ob容ktom tipa
klass, a imya dolzhno byt' imenem chlena etogo klassa. Rezul'tatom budet
poimenovannyj chlen ob容kta i on budet adresom, esli chlen yavlyaetsya
adresom.
Postfiksnoe vyrazhenie, za kotorym sleduet strelka (->) i imya,
yavlyaetsya postfiksnym vyrazheniem. Pervoe vyrazhenie dolzhno byt'
ukazatelem na ob容kt tipa klass, a imya dolzhno byt' imenem chlena
etogo klassa. Rezul'tatom budet poimenovannyj chlen ob容kta, na
kotoryj nastroen ukazatel' i on budet adresom, esli chlen yavlyaetsya
adresom. Znachit vyrazhenie E1->MOS tozhe samoe, chto (*E1).MOS.
Obratite vnimanie, chto "ob容kty tipa klass" mogut byt'
strukturami ($$R.9.2) ili ob容dineniyami ($$R.9.5). Klassy obsuzhdayutsya
v $$R.9.
R.5.2.5 Inkrement i dekrement
Znachenie, poluchaemoe v rezul'tate primeneniya postfiksnoj operacii ++,
est' znachenie operanda. Operand dolzhen byt' izmenyaemym adresom.
Tip operanda dolzhen byt' arifmeticheskij ili tip ukazatelya. Posle
vyborki rezul'tata (dlya dal'nejshego ispol'zovaniya) ob容kt uvelichivaetsya
na 1. Tip rezul'tata sovpadaet s tipom operanda, no ne yavlyaetsya
adresom (sm. tak zhe $$R.5.7 i $$R.5.17).
Postfiksnaya operaciya -- svoditsya k operacii dekrementa (umen'shenie
na 1) i analogichna operacii ++.
Vyrazheniya s unarnymi operaciyami vypolnyayutsya sprava nalevo.
unarnoe-vyrazhenie:
postfiksnoe-vyrazhenie
++ unarnoe vyrazhenie
-- unarnoe vyrazhenie
unarnaya-operaciya vyrazhenie-privedeniya
sizeof unarnaya-operaciya
sizeof ( imya-tipa )
vyrazhenie-razmeshcheniya
vyrazhenie-osvobozhdeniya
unarnaya-operaciya: odin iz
* & + - ! ~
Unarnaya operaciya * oznachaet kosvennost': vyrazhenie dolzhno byt'
ukazatelem, a rezul'tat yavlyaetsya adresom, ssylayushchimsya na ob容kt, na
kotoryj ukazyvaet vyrazhenie. Esli tip vyrazheniya est' "ukazatel' na T",
to tip rezul'tata budet "T".
Rezul'tatom unarnoj operacii & budet ukazatel' na ee operand.
Operand dolzhen byt' funkciej ili adresom ili konstrukciej
utochnennoe-imya. Dlya pervyh dvuh sluchaev, esli tip vyrazheniya
est' "T", to tip rezul'tata budet "ukazatel' na T". V chastnosti,
adres ob容kta tipa const T imeet tip const T*, tozhe verno dlya
volatile. Dlya sluchaya utochnennoe imya esli chlen klassa "C" ne yavlyaetsya
staticheskim i imeet tip "T", to tip rezul'tata operacii budet
"ukazatel' na chlen C tipa T". Dlya staticheskih chlenov tipa T
rezul'tatom budet obychnyj "ukazatel' na T". Adres peregruzhennoj
funkcii ($$R.13) mozhno brat' tol'ko pri inicializacii ili
prisvaivanii, v kotorom levaya chast' odnoznachno opredelyaet kakaya
versiya peregruzhennoj funkcii imeetsya vvidu ($R13.3).
Operand unarnoj operacii + dolzhen byt' arifmeticheskogo tipa
ili tipa ukazatel' i rezul'tatom budet znachenie operanda. Dlya
celochislennyh operandov proizvoditsya standartnoe preobrazovanie
celochislennyh. Tip rezul'tata est' tip preobrazovannogo operanda.
Operand unarnoj operacii - dolzhen imet' arifmeticheskij tip i
rezul'tatom budet izmenenie znaka operanda. Dlya celochislennyh
operandov vypolnyaetsya standartnoe preobrazovanie celochislennyh.
Operaciya dlya bezznakovyh velichin vypolnyaetsya s pomoshch'yu vychitaniya
znacheniya operanda iz 2**n, gde n chislo bitov v predstavlenii
preobrazovannogo operanda. Tip rezul'tata est' preobrazovannogo
operanda.
Operand operacii logicheskogo otricaniya ! dolzhen imet'
arifmeticheskij tip ili byt' ukazatelem, rezul'tat raven 1, esli
znachenie operanda est' 0, i raven 0, esli operand ne raven 0.
Tip rezul'tata est' int.
Operand operacii ~ dolzhen imet' celochislennyj tip, rezul'tatom
budet obrashchenie dvoichnogo predstavleniya operanda. Vypolnyayutsya
standartnye preobrazovaniya celochislennyh. Tip rezul'tata est'
tip preobrazovannogo operanda.
R.5.3.1 Inkrement i dekrement
Operand prefiksnoj operacii ++ uvelichivaetsya na 1. Operand dolzhen
byt' izmenyaemym adresom. Tip operanda dolzhen byt' arifmeticheskim
ili ukazatelem. Rezul'tatom yavlyaetsya novoe znachenie operanda,
ono schitaetsya adresom. Vyrazhenie ++x ekvivalentno x+=1. Dlya
utochneniya preobrazovanij mozhno obratit'sya k opisaniyu slozheniya
($$R.5.7) i operacij prisvaivaniya ($$R.5.17).
Prefiksnaya operaciya -- svoditsya k umen'sheniyu na 1 i vypolnyaetsya
analogichno prefiksnoj operacii ++.
Operaciya sizeof vychislyaet razmer svoego operanda v bajtah. Operand
dolzhen byt' ili vyrazheniem, kotoroe ne vychislyaetsya, ili imenem tipa
v skobkah. Operaciyu sizeof nel'zya primenyat' k funkcii, bitovomu polyu,
neopredelennomu klassu, tipu void ili k massivu s neukazannymi
granicami indeksov. Bajt nikak ne opredelyaetsya yazykom, krome kak
rezul'tata operacii sizeof, imenno sizeof(char) est' 1.
Esli operaciya primenyaetsya k ssylke, rezul'tatom budet razmer
ob容kta, na kotoryj nastroena ssylka. Esli ona primenyaetsya k klassu,
rezul'tatom budet razmer ob容kta etogo klassa v bajtah s uchetom
vseh dopolnitel'nyh bajtov, kotorye potrebuetsya dlya razmeshcheniya
takogo ob容kta v massive. Razmer lyubogo klassa ili ob容kta klassa
bol'she nulya. V sluchae massiva operaciya vydaet polnoe chislo bajtov
v massive. Otsyuda sleduet, chto razmer massiva iz n elementov raven
razmeru elementa, umnozhennomu na n.
Operaciya sizeof mozhet primenyat'sya k ukazatelyu na funkciyu, no ne
k samoj funkcii.
Rezul'tatom operacii budet konstanta tipa size_t. |tot tip
opredelen v standartnom zagolovochnom fajle <stddef.h> i yavlyaetsya
zavisyashchim ot realizacii bezznakovym celochislennym tipom.
Operaciya new prednaznachena dlya sozdaniya ob容kta tipa imya-tipa
($$R.8.1). |tot tip dolzhen byt' tipom ob容kta i funkcii nel'zya
razmeshchat' s ee pomoshch'yu, hotya ukazateli na funkcii mozhno.
vyrazhenie-razmeshcheniya:
::opt new parametry-new opt imya-tipa-new inicializator-new
::opt new parametry-new opt ( imya-tipa ) inicializator-new
parametry-new:
( spisok-vyrazhenij )
imya-tipa-new:
spisok-specifikacij-tipa opisatel'-new opt
opisatel'-new:
* spisok-specifikacij-cv opt opisatel'-new opt
imya-klassa :: spisok-specifikacij-cv opt opisatel'-new opt
opisatel'-new opt [ vyrazhenie ]
inicializator-new:
( spisok-inicializatorov opt )
Vremya zhizni ob容kta, sozdannogo s pomoshch'yu new, ne ogranichivaetsya
oblast'yu vidimosti, v kotoroj on byl sozdan. Operaciya new vozvrashchaet
ukazatel' na sozdannyj ob容kt. Esli ob容kt yavlyaetsya massivom,
vozvrashchaetsya ukazatel' na nachal'nyj element massiva. Naprimer,
obe operacii new int i new int[1] vozvratyat int* , a tipom
new int[i][10] budet int(*)[10]. Esli opisyvaetsya tip massiva
($$R.8.2.4), vse razmernosti, krome pervoj, dolzhny byt' vyrazheniyami-
konstantami ($$R.5.19) s polozhitel'nym znacheniem. Pervaya razmernost'
massiva mozhet zadavat'sya proizvol'nym vyrazheniem, dazhe esli
ispol'zuetsya imya-tipa (zdes' narushaetsya obshchee trebovanie, chtoby
razmernosti massiva v konstrukcii imya-tipa byli
vyrazheniyami-konstantami ($$R.5.19)).
Dopuskaetsya, chtoby vyzyvalas' funkciya operator new() s parametrom
nul'. V takom sluchae vozvrashchaetsya ukazatel' na ob容kt. Pri povtorenii
takih vyzovov budut vozvrashchat'sya ukazateli na raznye ob容kty.
Konstrukciya spisok-specifikacij-tipa ne dolzhna soderzhat' const,
volatile, opisanie klassa ili perechisleniya.
Dlya rezervirovaniya pamyati operaciya new obrashchaetsya k funkcii
operator new() ($$R.12.5). Pri razmeshchenii ob容kta tipa T ej v
kachestve pervogo parametra peredaetsya sizeof(T). Konstrukciya
parametry-new ispol'zuetsya dlya peredachi dopolnitel'nyh parametrov.
Naprimer, operaciya new T privodit k vyzovu operator new(sizeof(T)),
a operaciya new(2,f) T privodit k vyzovu operator new(sizeof(T),2,f).
Konstrukciya parametry-new mozhet ispol'zovat'sya tol'ko, esli
opisana funkciya operator new() s parametrami sootvetstvuyushchih tipov.
Esli s pomoshch'yu operacii new sozdaetsya ob容kt ne tipa klass
(v tom chisle i massiv ob容ktov tipa klass), to vyzyvaetsya global'naya
funkciya ::operator new(). Esli s pomoshch'yu new sozdaetsya ob容kt klassa
T, vyzyvaetsya funkciya T::operator new(), esli ona sushchestvuet
(ispol'zuya obychnye pravila prosmotra pri poiske chlenov klassa i ego
bazovyh klassov, $$R.10.1.1), inache vyzyvaetsya global'naya funkciya
::operator new(). Ispol'zovanie operacii ::new() garantiruet, chto
budet vyzyvat'sya global'naya funkciya ::operator new(), dazhe esli
sushchestvuet T::operator new().
Konstrukciya vyrazhenie-razmeshcheniya mozhet soderzhat' inicializator-new.
Dlya ob容ktov klassov s konstruktorami ($$R.12.1) zadavaemyj eyu
spisok parametrov budet ispol'zovat'sya pri vyzove konstruktora, v
drugih sluchayah konstrukciya inicializator-new dolzhna imet' vid
( vyrazhenie ) ili ( ). Esli vyrazhenie prisutstvuet, ono ispol'zuetsya
dlya inicializacii ob容kta, esli ego net, ob容kt nachnet sushchestvovanie
s neopredelennym znacheniem.\
Esli klass imeet konstruktor, ob容kt etogo klassa mozhno sozdat'
s pomoshch'yu new tol'ko pri uslovii, chto zadany podhodyashchie parametry,
ili, chto klass imeet standartnyj konstruktor ($$R.12.1).
Otvodit li pamyat' pri sozdanii ob容kta tipa klass sama funkciya
operator new, ili ostavlyaet eto na konstruktor, zavisit ot realizacii.
Kak dlya konstruktora, tak i dlya funkcii operator new() provoditsya
proverka vozmozhnosti dostupa i odnoznachnosti ($$R.12).
Dlya massivov nel'zya zadavat' inicializatory. Massivy ob容ktov
tipa klassa s konstruktorom mozhno sozdavat' s pomoshch'yu operacii new
tol'ko, esli konstruktor klassa yavlyaetsya standartnym ($$R.12.1).
V etom sluchae standartnyj konstruktor budet vyzyvat'sya dlya kazhdogo
elementa massiva.
Inicializaciya proizvoditsya tol'ko v tom sluchae, kogda funkciya
operator new() vozvrashchaet nenul'. Esli ona vozvrashchaet 0 (pustoj
ukazatel'), znachenie vyrazheniya est' 0.
Poryadok vychisleniya vyrazheniya vyzova operator new() dlya polucheniya
pamyati i poryadok vychisleniya parametrov konstruktora neopredelen.
Tak zhe neopredeleno vychislyayutsya li parametry konstruktora, esli
funkciya operator new() vozvratila 0.
V konstrukcii imya-tipa-new skobki ispol'zovat' neobyazatel'no.
Togda obrashchenie
new int (*[10])(); // error
mozhet privesti k oshibke, t.k. operacii primenyayutsya v takom poryadke
(new int) (*[10])(); // error
Ob容kty slozhnogo tipa mozhno zadat' v operacii new s pomoshch'yu yavno
ukazannyh skobok, naprimer, obrashchenie
new (int (*[10])());
razmeshchaet massiv iz 10 ukazatelej na funkcii (ne imeyushchie parametrov
i vozvrashchayushchie int).
Konstrukcii imya-tipa-new v vyrazhenie-razmeshcheniya dolzhna byt'
samoj dlinnoj iz vozmozhnyh posledovatel'nostej konstrukcij
opisatel'-new. |to predotvrashchaet kollizii mezhdu operaciyami iz
opisatelej &, *, [] i ih dvojnikami iz vyrazheniya, naprimer,
new int* i; // syntax error: parsed as `(new int*) i'
// not s `(new int)*i'
Simvol * ispol'zuetsya v opisatele ukazatelya, a ne v kachestve
operacii umnozheniya.
Operaciya delete unichtozhaet ob容kt, sozdannyj s pomoshch'yu new.
vyrazhenie-osvobozhdeniya:
::opt delete vyrazhenie-privedeniya
::opt delete [] vyrazhenie-privedeniya
Rezul'tat imeet tip void. Operandom delete dolzhen byt' ukazatel',
kotoryj vozvrashchaet new. |ffekt primeneniya operacii delete k ukazatelyu,
kotoryj ne poluchen v rezul'tate operacii new bez zadaniya
parametry-new, schitaetsya neopredelennym i obychno privodit k opasnym
posledstviyam. Odnako garantiruetsya, chto udalenie po ukazatelyu s
nulevym znacheniem bezopasno.
Rezul'tat popytki dostupa k udalennomu ob容ktu neopredelen, a
udalenie ob容kta mozhet izmenit' ego znachenie. Bolee togo, esli
vyrazhenie, zadayushchee ob容kt, yavlyaetsya izmenyaemym adresom, ego
znachenie posle udaleniya neopredeleno.
Nel'zya udalyat' ukazatel' na konstantu.
Operaciya delete vyzyvaet destruktor (esli on est' $$12.4)
dlya ob容kta, na kotoryj nastroen ee operand.
Dlya osvobozhdeniya pamyati, otvedennoj pod ukazyvaemyj ob容kt,
operaciya delete vyzyvaet funkciyu operator delete ($$R.12.5).
Dlya ob容ktov, ne imeyushchih tip klass (v tom chisle i dlya massivov
klassov), ispol'zuetsya global'naya funkciya ::operator delete().
Dlya ob容kta tipa klass T vyzyvaetsya funkciya T::operator delete(),
esli ona est' (ispol'zuya obychnye pravila prosmotra pri poiske
chlenov klassa i proizvodnyh ot nego klassov, $$R.10.1.1), v
protivnom sluchae vyzyvaetsya global'naya funkciya ::operator delete().
Obrashchenie ::delete garantiruet, chto budet vyzyvat'sya global'naya
funkciya ::operator delete(), dazhe esli sushchestvuet T::operator delete().
Dlya udaleniya massivov ispol'zuetsya obrashchenie vida
delete [ ] vyrazhenie-privedeniya
Zdes' vyrazhenie dolzhno ukazyvat' na massiv. Esli est' destruktory,
oni budut vyzyvat'sya dlya udaleniya ukazannyh ob容ktov.
Rezul'tat udaleniya massiva s pomoshch'yu prostogo obrashcheniya delete
neopredelen, tak zhe kak i udalenie odinochnogo ob容kta s pomoshch'yu
delete [].
R.5.4 YAvnoe preobrazovanie tipa
YAvnoe preobrazovanie tipa mozhno zadat' s pomoshch'yu funkcional'noj
zapisi ($$R.5.2.3) ili s pomoshch'yu operacii privedeniya.
vyrazhenie-privedeniya:
unarnoe-vyrazhenie
( imya-tipa ) vyrazhenie-privedeniya
Zadanie s pomoshch'yu operacii privedeniya ispol'zuetsya dlya oboznacheniya
preobrazovaniya k tipu, kotoryj ne yavlyaetsya konstrukciej
imya-prostogo-tipa.
V operacii privedeniya nel'zya opredelyat' tipy.
Vsyakoe preobrazovanie tipa, ne upomyanutoe zdes' i ne yavlyayushcheesya
preobrazovaniem yavno opredelennym pol'zovatelem ($$R.12.3), schitaetsya
oshibkoj.
Lyuboj tip, kotoryj mozhno preobrazovat' v drugoj s pomoshch'yu
standartnogo preobrazovaniya ($$R.4), mozhno takzhe preobrazovat'
s pomoshch'yu yavnogo preobrazovaniya (privedeniya) i smysl preobrazovaniya
budet tot zhe.
Ukazatel' mozhno preobrazovat' k lyubomu celochislennomu tipu,
dostatochno bol'shomu, chtoby vmestit' znachenie ukazatelya. Algoritm
preobrazovaniya zavisit ot realizacii, no predpolagaetsya, chto on
budet estestvennym dlya togo, kto znaet sistemu adresacii, ispol'zuemoj
mashiny.
Znachenie celochislennogo tipa mozhet byt' yavno preobrazovano v
ukazatel'. Ukazatel', preobrazovannyj v celoe dostatochnogo razmera
(esli takie est' v realizacii), i preobrazovannyj obratno k tipu
ukazatelya, dolzhen imet' svoe pervonachal'noe znachenie. Vse drugie
detali perevoda ukazatelya v celoe i obratno zavisyat ot realizacii.
Ukazatel' na ob容kt odnogo tipa mozhet byt' preobrazovan v
ukazatel' na ob容kt drugogo tipa (s soblyudeniem ogranichenij, ukazannyh
zdes'). Ispol'zovanie poluchivshegosya ukazatelya mozhet vyzvat'
osobuyu adresnuyu situaciyu ("nevernyj adres"), esli preobrazuemyj
ukazatel' ne
nastroen na ob容kt, pravil'nym obrazom vyravnennyj v pamyati.
Garantiruetsya, chto ukazatel' na ob容kt dannogo razmera mozhno
preobrazovat' v ukazatel' na ob容kt ravnogo ili men'shego razmera
i provesti obratnoe preobrazovanie bez izmeneniya znacheniya ukazatelya.
Na razlichnyh mashinah dvoichnoe predstavlenie ukazatelej mozhet byt'
razlichno kak i trebovaniya na vyravnivaniya ob容ktov. Sostavnye
ob容kty vyravnivayutsya po samoj strogoj granice, trebuemoj ih
sostavlyayushchimi. Ukazatel' tipa void* schitaetsya sovmestimym s
ukazatelem na ob容kt lyubogo tipa.
Ukazatel' na klass B mozhno preobrazovat' v ukazatel' na klass D,
dlya kotorogo klass B yavlyaetsya pryamo ili oposredovanno bazovym
klassom, esli sushchestvuet odnoznachnoe preobrazovanie iz D v B
($$R.4.6, $$.R10.1.1) i esli B yavlyaetsya virtual'nym bazovym klassom
($$R.10.1). Takoe privedenie ot bazovogo klassa k proizvodnomu
klassu predpolagaet, chto ob容kt bazovogo klassa yavlyaetsya vlozhennym
po otnosheniyu k ob容ktu proizvodnogo klassa. V rezul'tate poluchitsya
ukazatel', nastroennyj na ob容mlyushchij ob容kt proizvodnogo klassa.
Esli ob容kt bazovogo klassa ne soderzhitsya ni v kakom ob容kte
proizvodnogo klassa, takaya operaciya privedeniya mozhet vyzvat'
osobuyu situaciyu.
Pustoj ukazatel' (0) preobrazuetsya sam v sebya.
Poka eshche neopredelennyj klass mozhno ispol'zovat' v operacii
privedeniya ukazatelya, v etom sluchae nikakih dopushchenij o strukture
klassa ne delaetsya ($$R.10.1).
Lyuboj ob容kt mozhno yavno preobrazovat' k tipu ssylki X&, esli
ukazatel' na etot ob容kt mozhno yavno preobrazovat' v tip X*.
V rezul'tate privedeniya k ssylke ne proishodit vyzovov konstruktorov
ili funkcij preobrazovanij. Preobrazovanie ssylki na bazovyj klass
v ssylku na proizvodnyj klass rassmatrivaetsya analogichno
preobrazovaniyu ukazatelya na bazovyj klass v ukazatel' na
proizvodnyj klass, uchityvaya voprosy odnoznachnosti, virtual'nyh
klassov i t.d.
Rezul'tatom privedeniya k ssylke yavlyaetsya adres, v otlichie ot vseh
ostal'nyh privedenij. Rezul'tat privedeniya ukazatelya ili ssylki
nastroen na tot zhe ob容kt, chto i ishodnoe vyrazhenie bez operacii
privedeniya.
Ukazatel' na funkciyu mozhno yavno preobrazovat' v ukazatel' na
nekotoryj ob容kt pri uslovii, chto tip ukazatelya na etot ob容kt
dostatochno velik, chtoby hranit' ukazatel' na funkciyu. Ukazatel'
na nekotoryj ob容kt mozhno yavno preobrazovat' v ukazatel' na funkciyu
pri uslovii, chto tip ukazatelya na funkciyu dostatochno velik, chtoby
hranit' ukazatel' na etot ob容kt. V oboih sluchayah, ispol'zovanie
ukazatelya, poluchivshegosya v rezul'tate preobrazovaniya, mozhet
vyzvat' osobuyu adresnuyu situaciyu, ili chto-nibud' pohuzhe,
esli ishodnyj ukazatel' ne nastroen na sootvetstvuyushchij ob容kt.
Ukazatel' na funkciyu odnogo tipa mozhno yavno preobrazovat' v
ukazatel' na funkciyu drugogo tipa. Rezul'tat vyzova funkcii s
pomoshch'yu ukazatelya na funkciyu, tip kotoroj otlichen ot tipa,
ispol'zovannogo pri opredelenii pervoj funkcii, neopredelen
(sm. tak zhe $$R.4.6).
Ob容kt ili znachenie mozhno preobrazovat' v ob容kt tipa klass
tol'ko pri uslovii, chto opredelen podhodyashchij konstruktor ili
operaciya preobrazovaniya ($$R.12.3).
Ukazatel' na chlen mozhno yavno preobrazovat' v ukazatel' na drugoj
chlen, esli oba uchastvuyushchih tipa yavlyayutsya tipami ukazatelej
na chleny odnogo klassa, ili, esli oba tipa yavlyayutsya ukazatelyami
na funkciyu-chlen klassov, odin iz kotoryh poluchaetsya kak odnoznachnoe
proizvodnoe ot drugogo ($$R.4.8).
Ukazatel' na ob容kt s tipom, imeyushchim specifikaciyu const, mozhno
privesti k ukazatelyu s tipom bez specifikacii const. Poluchivshijsya
v rezul'tate ukazatel' budet nastroen na ishodnyj ob容kt.
Ob容kt s tipom, imeyushchim specifikaciyu const, ili ssylku na ob容kt
takogo tipa mozhno privesti v ssylku na ob容kt s tipom bez const.
Poluchivshayasya v rezul'tate ssylka budet nastroena na ishodnyj
ob容kt. V rezul'tate popytki izmenit' etot ob容kt s pomoshch'yu
takoj ssylki ili ukazatelya mozhet vozniknut' osobaya situaciya ili
on budet takim zhe, kak pri obrashchenii s pomoshch'yu ishodnoj ssylki
ili ukazatelya k ob容ktu, tip kotorogo ne soderzhit const. Vozniknet
li osobaya adresnaya situaciya zavisit ot realizacii.
Ukazatel' na ob容kt tipa so specifikaciej volatile mozhno privesti
k ukazatelyu na ob容kt tipa bez volatile. V rezul'tate poluchitsya
ukazatel', nastroennyj na ishodnyj ob容kt. Ob容kt tipa s volatile
ili ssylku na takoj ob容kt mozhno privesti k ssylke na ob容kt s tipom
bez volatile.
R.5.5 Operacii ukazatel'-na-chlen
Operacii ukazatel'-na-chlen primenyayutsya sleva napravo.
vyrazhenie-pm:
vyrazhenie-privedeniya
vyrazhenie-pm .* vyrazhenie-privedeniya
vyrazhenie-pm ->* vyrazhenie-privedeniya
Binarnaya operaciya .* svyazyvaet svoj vtoroj operand, kotoryj dolzhen
imet' tip "ukazatel' na chlen klassa T", s pervym operandom, imeyushchim
tip klass T ili takoj klass, dlya kotorogo T yavlyaetsya odnoznachno
opredelennym i dostizhimym bazovym klassom. Rezul'tatom budet ob容kt
ili funkciya s tipom, zadavaemym vtorym operandom.
Binarnaya operaciya ->* svyazyvaet svoj vtoroj operand, kotoryj dolzhen
imet' tip "ukazatel' na chlen klassa T", s pervym operandom, imeyushchim
tip "ukazatel' na T" ili tip "ukazatel' na klass, dlya kotorogo T
yavlyaetsya odnoznachno opredelennym i dostizhimym bazovym klassom".
Rezul'tatom budet ob容kt ili funkciya s tipom, zadavaemym vtorym
operandom.
Esli rezul'tat .* ili ->* est' funkciya, to ego mozhno ispol'zovat'
tol'ko v kachestve operanda operacii vyzova funkcii (), naprimer,
operaciya
(ptr_to_obj->*ptr_to_mfct)(10);
privodit k vyzovu funkcii-chlena, oboznachennoj ptr_to_mfct, dlya
ob容kta, na kotoryj nastroen ukazatel' ptr_to_obj. Rezul'tat
operacii .* ili ->* yavlyaetsya adresom, esli vtoroj operand est'
adres.
R.5.6 Mul'tiplikativnye operacii
Mul'tiplikativnye operacii *, /, i % vypolnyayutsya sleva napravo.
Mul'tiplikativnoe-vyrazhenie:
vyrazhenie-pm
mul'tiplikativnoe-vyrazhenie * vyrazhenie-pm
mul'tiplikativnoe-vyrazhenie / vyrazhenie-pm
mul'tiplikativnoe-vyrazhenie % vyrazhenie-pm
Operandy operacij * i / dolzhny imet' arifmeticheskij tip, operandy
dlya % dolzhny byt' celochislennogo tipa. Obychnye arifmeticheskie
preobrazovaniya ($$R.4.5) proizvodyatsya nad operandami i opredelyayut
tip rezul'tata.
Binarnaya operaciya * oboznachaet umnozhenie.
Binarnaya operaciya / vychislyaet chastnoe, a binarnaya operaciya %
vychislyaet ostatok ot deleniya pervogo vyrazheniya na vtoroe. Esli
vtoroj operand u / ili % est' 0, rezul'tat neopredelen, inache
(a/b)*b + a%b dolzhno ravnyat'sya a. Esli oba operanda neotricatel'ny,
to takim zhe budet i rezul'tat, v protivnom sluchae znak rezul'tata
opredelyaetsya realizaciej.
R.5.7 Additivnye operacii
Additivnye operacii + i - vypolnyayutsya sleva napravo, pri etom
proishodyat obychnye arifmeticheskie preobrazovaniya ($$R.4.5)
operandov arifmeticheskogo tipa.
additivnoe-vyrazhenie:
mul'tiplikativnoe-vyrazhenie
additivnoe vyrazhenie + mul'tiplikativnoe-vyrazhenie
additivnoe-vyrazhenie - mul'tiplikativnoe-vyrazhenie
Operandy dolzhny byt' arifmeticheskogo tipa ili tipa ukazatelya.
Rezul'tatom operacii + yavlyaetsya summa operandov. Mozhno skladyvat'
ukazatel' na ob容kt v massive i znachenie lyubogo celochislennogo tipa.
Rezul'tatom budet ukazatel' togo zhe tipa, chto i ishodnyj ukazatel',
no on budet nastroen na drugoj ob容kt massiva
s zadannym smeshcheniem ot ishodnogo ob容kta. Tak, esli P
est' ukazatel' na ob容kt massiva, vyrazhenie P+1 yavlyaetsya ukazatelem
na sleduyushchij ob容kt massiva. Esli zhe poluchivshijsya v rezul'tate
slozheniya ukazatel' vyshel za granicy massiva, rezul'tat budet
neopredelennym, krome sluchaya, kogda ukazatel' nastroen na pervyj adres
bol'shij verhnej granicy massiva.
Rezul'tatom operacii - budet raznost' operandov. Znachenie
lyubogo celochislennogo tipa mozhno vychitat' iz ukazatelya, pri etom
primenyayutsya te zhe preobrazovaniya, chto i dlya operacii +.
Nikakie drugie sochetaniya tipov dlya ukazatelej ne dopustimy.
Esli vychitayutsya dva ukazatelya na ob容kty odnogo tipa, rezul'tatom
budet celochislennoe znachenie so znakom, kotoroe pokazyvaet na skol'ko
ob容ktov etogo tipa otstoyat drug ot druga ukazuemye ob容kty. Ukazateli
na sosednie elementy massiva otstoyat na 1. Tip rezul'tata zavisit ot
realizacii, no on dolzhen byt' opredelen kak ptrdiff_t v standartnom
zagolovochnom fajle <stddef.h>. Rezul'tat ne opredelen, esli ukazateli
ne nastroeny na elementy odnogo massiva. Esli P est' ukazatel'
na poslednij element massiva, to (P+1) - 1 est' P.
Operacii sdvigov << i >> vypolnyayutsya sleva napravo.
sdvigovoe-vyrazhenie:
additivnoe-vyrazhenie
sdvigovoe-vyrazhenie << additivnoe vyrazhenie
sdvigovoe-vyrazhenie >> additivnoe vyrazhenie
Operandy dolzhny byt' celochislennogo tipa, i nad nimi proizvodyatsya
standartnye celochislennye preobrazovaniya. Tip rezul'tata sovpadaet
s tipom preobrazovannogo levogo operanda. Rezul'tat ne opredelen,
esli pravyj operand otricatelen ili bol'she ili raven chislu razryadov
v dvoichnom predstavlenii preobrazovannogo levogo operanda.
Znacheniem vyrazheniya E1<<E2 budet E1 (rassmatrivaemoe kak nabor
razryadov), sdvinutoe vlevo na E2 razryadov, prichem osvobodivshiesya
razryady zapolnyayutsya nulyami. Znacheniem vyrazheniya E1>>E2 budet E1,
sdvinutoe vpravo na E2 razryadov. Esli E1 bezznakovogo tipa ili
imeet neotricatel'noe znachenie, garantiruetsya, chto sdvig vpravo
- logicheskij (zapolnenie nulyami), inache rezul'tat zavisit ot realizacii.
R.5.9 Operacii otnosheniya
Operacii otnosheniya vypolnyayutsya sleva napravo, no etot fakt malo chto
daet, ibo vyrazhenie a<b<c oznachaet (a<b)<c, a vovse ne (a<b)&&(b<c).
vyrazhenie-otnosheniya:
sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya < sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya > sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya <= sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya >= sdvigovoe-vyrazhenie
Operandy dolzhny byt' arifmeticheskogo tipa ili tipa ukazatelej.
Operacii < (men'she chem), > (bol'she chem), <= (men'she ili ravno) i
>= (bol'she ili ravno) dayut rezul'tat 0, esli ukazannoe otnoshenie
ne vypolnyaetsya, i 1, esli ono vypolnyaetsya. Tip rezul'tata int.
Nad arifmeticheskimi operandami vypolnyayutsya obychnye arifmeticheskie
preobrazovaniya. Nad ukazatelyami vypolnyayutsya obychnye preobrazovaniya
ukazatelej. Predpolagaetsya, chto lyuboj ukazatel' mozhno sravnit'
s vyrazheniem, imeyushchim rezul'tat 0, i lyuboj ukazatel' mozhno sravnit'
s ukazatelem, imeyushchim tip void* (v etom sluchae ukazatel' snachala
preobrazuetsya k tipu void*). Ukazateli na ob容kty ili funkcii
odnogo tipa (posle preobrazovaniya ukazatelej) mozhno sravnivat',
rezul'tat zavisit ot vzaimnogo raspolozheniya v pamyati ob容ktov ili
funkcij.
Dva ukazatelya na odin i tot zhe ob容kt schitayutsya ravnymi. Esli
dva ukazatelya nastroeny na nestaticheskie chleny odnogo ob容kta, to
ukazatel', nastroennyj na chlen, opisannyj pozdnee, schitaetsya
bol'shim, pri uslovii, chto chleny ne imeyut raznyh specifikacij
ukazatel'-dostupa ($$R.11.1), a klass ne yavlyaetsya ob容dineniem.
Esli dva ukazatelya nastroeny na nestaticheskie chleny odnogo ob容kta
i specifikacii ukazatelej-dostupa ($$R.11.1) etih chlenov razlichny,
rezul'tat budet ne opredelen. Esli dva ukazatelya nastroeny na chleny
(dannye) odnogo i togo zhe ob容dineniya, oni schitayutsya ravnymi. Esli dva
ukazatelya nastroeny na elementy odnogo massiva ili smotryat za granicu
massiva, to ukazatel', nastroennyj na element s bol'shim indeksom,
budet bol'shim. Vse drugie sravneniya ukazatelej opredelyayutsya
realizaciej.
R.5.10 Operacii sravneniya na ravenstvo
vyrazhenie-ravenstva:
vyrazhenie-otnosheniya
vyrazhenie-ravenstva == vyrazhenie-otnosheniya
vyrazhenie-ravenstva != vyrazhenie-otnosheniya
Operacii == (ravno) i != (ne ravno) analogichny operaciyam
otnosheniya, za isklyucheniem togo, chto ih prioritet nizhe. (Takim obrazom,
operaciya a<b == c<d daet rezul'tat 1, esli vyrazheniya a<b i c<d
imeyut odno i to zhe znachenie.)
Krome etogo, mozhno sravnivat' ukazateli na chleny odnogo tipa.
Proizvodyatsya preobrazovaniya ukazatelya na chlen ($$R.4.8). Ukazatel'
na chlen mozhno sravnit' s vyrazheniem-konstantoj, kotoroe daet
rezul'tat 0.
R.5.11 Porazryadnaya operaciya I
vyrazhenie-I:
vyrazhenie-ravenstva
vyrazhenie-I & vyrazhenie-ravenstva
Vypolnyayutsya obychnye arifmeticheskie preobrazovaniya, rezul'tat -
porazryadnaya funkciya I ot operandov. Operaciya primenima tol'ko k
celochislennym operandam.
R.5.12 Porazryadnaya (isklyuchayushchaya) operaciya ILI
vyrazhenie-isklyuchayushchego-ILI:
vyrazhenie-I
vyrazhenie-isklyuchayushchego-ILI ^ vyrazhenie-I
Vypolnyayutsya obychnye arifmeticheskie preobrazovaniya, rezul'tat -
porazryadnaya isklyuchayushchaya funkciya ILI ot operandov. Operaciya primenima
tol'ko k celochislennym operandam.
R.5.13 Porazryadnaya (vklyuchayushchaya) operaciya ILI
vyrazhenie-ILI:
vyrazhenie-isklyuchayushchego-ILI
vyrazhenie-ILI | vyrazhenie-isklyuchayushchego-ILI
Vypolnyayutsya obychnye arifmeticheskie preobrazovaniya, rezul'tat -
porazryadnaya funkciya ILI ot operandov. Operaciya primenima tol'ko
k celochislennym tipam.
R.5.14 Logicheskaya operaciya I
logicheskoe-vyrazhenie-I:
vyrazhenie-ILI
logicheskoe-vyrazhenie-I && vyrazhenie-ILI
Operacii && vypolnyayutsya sleva napravo. Takaya operaciya daet rezul'tat
1, esli oba operanda ee otlichny ot nulya, inache rezul'tat - 0. V
otlichie ot & pri operacii && garantiruetsya vychislenie sleva napravo,
bolee togo, vtoroj operand ne vychislyaetsya, esli pervyj operand raven 0.
Operandy ne obyazatel'no imeyut odinakovyj tip, no kazhdyj dolzhen byt'
arifmeticheskogo tipa ili tipa ukazatelya. Tip rezul'tata int. Vse
pobochnye effekty vychisleniya pervogo vyrazheniya mogut voznikat' do
vychisleniya vtorogo vyrazheniya.
R.5.15 Logicheskaya operaciya ILI
logicheskoe-vyrazhenie-ILI:
logicheskoe-vyrazhenie-I
logicheskoe-vyrazhenie-ILI || logicheskoe-vyrazhenie-I
Operacii || vypolnyayutsya sleva napravo. Rezul'tat operacii 1, esli
odin iz ee operandov otlichen ot nulya, inache rezul'tat - 0. V otlichie
ot | pri operacii || garantiruetsya vychislenie sleva napravo, bolee
togo, vtoroj operand ne vychislyaetsya, esli znachenie pervogo operanda
otlichno ot nulya.
Operandy ne obyazatel'no imeyut odinakovyj tip, no kazhdyj dolzhen byt'
arifmeticheskogo tipa ili tipa ukazatelya. Tip rezul'tata int. Vse
pobochnye effekty vychisleniya pervogo vyrazheniya mogut voznikat' do
vychisleniya vtorogo vyrazheniya.
R.5.16 Operaciya usloviya
vyrazhenie-usloviya:
logicheskoe-vyrazhenie-ILI
logicheskoe-vyrazhenie-ILI ? vyrazhenie : vyrazhenie-usloviya
Uslovnye vyrazheniya vypolnyayutsya sleva napravo. Pervoe vyrazhenie dolzhno
byt' arifmeticheskogo tipa ili tipa ukazatelya. Ono vychislyaetsya, i,
esli rezul'tat ego otlichen ot nulya, to rezul'tatom uslovnogo vyrazheniya
budet znachenie vtorogo vyrazheniya, inache rezul'tat - znachenie tret'ego
vyrazheniya. Vse pobochnye effekty vychisleniya pervogo vyrazheniya mogut
voznikat' do vychisleniya vtorogo ili tret'ego vyrazheniya.
Esli vtoroe i tret'e vyrazhenie arifmeticheskogo tipa, i tipy ih
sovpadayut, to takim zhe budet i tip rezul'tata, esli oni razlichayutsya, to
vypolnyayutsya obychnye arifmeticheskie preobrazovaniya, chtoby privesti ih
k obshchemu tipu. Esli vtoroe i tret'e vyrazhenie yavlyayutsya
ukazatelyami ili vyrazheniem-konstantoj, dayushchim rezul'tat 0, vypolnyayutsya
preobrazovaniya ukazatelej, chtoby privesti rezul'taty vyrazhenij k
obshchemu tipu. Esli vtoroe i tret'e vyrazhenie yavlyayutsya ssylkami,
vypolnyaetsya preobrazovanie ssylok, chtoby privesti ih k obshchemu tipu.
Esli vtoroe i tret'e vyrazhenie imeyut tip void, obshchij tip
budet void. Esli vtoroe i tret'e vyrazhenie imeyut odin tip
klass T, obshchim tipom budet T. Inache, vyrazhenie schitaetsya nedopustimym.
Tip rezul'tata est' obshchij tip. Vychislyaetsya tol'ko vtoroe ili tret'e
vyrazhenie (no ne oba). Rezul'tat budet adresom, esli vtoroj i
tretij operand odnogo tipa i yavlyayutsya adresami.
R.5.17 Operacii prisvaivaniya
Sushchestvuet neskol'ko operacij prisvaivaniya, vse oni vypolnyayutsya
sprava nalevo. Dlya vseh nih trebuetsya, chtoby levym operandom byl
izmenyaemyj adres. Tip vyrazheniya prisvaivaniya sovpadaet s tipom
levogo operanda. Rezul'tat operacii prisvaivanie - znachenie,
hranyashcheesya v levom operande posle togo kak proizoshlo prisvaivanie.
Rezul'tat yavlyaetsya adresom.
vyrazhenie-prisvaivaniya:
vyrazhenie-usloviya
unarnoe-vyrazhenie operaciya-prisvaivaniya vyrazhenie-prisvaivaniya
operaciya-prisvaivaniya: odin iz
= *= /= %= += -= >>= <<= &= ^= |=
Pri prostom prisvaivanii (=) znachenie vyrazheniya zamenyaet soboj znachenie
ob容kta, s kotorym sopostavlyaetsya levyj operand. Esli oba operanda
arifmeticheskogo tipa, pravyj operand, prezhde chem proizojdet
prisvaivanie, preobrazuetsya k tipu levogo operanda. Neyavnye
preobrazovaniya k tipu perechisleniya ($$R.7.2) ne proizvodyatsya, poetomu
esli levyj operand imeet tip perechisleniya, pravyj operand dolzhen
byt' takim zhe. Esli levyj operand imeet tip ukazatelya, pravyj
operand dolzhen byt' tipa ukazatelya ili vyrazheniem-konstantoj, dayushchim
rezul'tat 0. Pravyj operand preobrazuetsya k tipu levogo operanda,
prezhde vypolneniya prisvaivaniya.
Ukazatel' tipa T* const mozhno prisvaivat' ukazatelyu tipa T*, no
obratnoe prisvaivanie schitaetsya nezakonnym ($$R.7.1.6). Ob容kty
tipa const T ili volatile T mozhno prisvaivat' po adresu tipa T ili
volatile T (sm. tak zhe $$R.8.4).
Esli levyj operand imeet tip ukazatelya na chlen, pravyj operand
dolzhen byt' tipa ukazatel' na chlen ili vyrazheniem-konstantoj,
dayushchim rezul'tat 0; pered prisvaivaniem pravyj operand preobrazuetsya
k tipu levogo operanda.
Prisvaivanie ob容ktam klassa X ($$R.9) zadaetsya funkciej
X::operator=() ($$R.13.4.3). Esli pol'zovatel' ne opredelil
svoyu funkciyu X::operator=(), dlya prisvaivaniya ispol'zuetsya
standartnyj variant ($$R.12.8). Otsyuda sleduet, chto ob容kt klassa,
kotoryj yavlyaetsya pryamym ili nepryamym proizvodnym ot X, i
odnoznachno opisan kak proizvodnyj v chasti public ($$R.4.6),
mozhno prisvoit' ob容ktu X.
Ukazatel' na chlen klassa B mozhno prisvaivat' ukazatelyu na chlen
togo zhe tipa klassa D pri uslovii, chto D yavlyaetsya pryamym ili
nepryamym proizvodnym klassa B, i odnoznachno opisan kak
proizvodnyj v chasti public ($$R.10.1.1).
Prisvaivanie ob容ktu tipa "ssylka na T" svoditsya k prisvaivaniyu
ob容ktu tipa T, kotoryj oboznachaetsya ssylkoj.
Vypolnenie vyrazhenie vida E1 op= E2 ekvivalentno vypolneniyu
E1 = E1 op (E2), odnako E1 vychislyaetsya lish' odin raz. V operaciyah
+= i -= levyj operand mozhet byt' ukazatelem, v etom sluchae pravyj
(celochislennyj) operand preobrazuetsya tak, kak ob座asnyalos' v $$R.5.7.
Vse pravye operandy i vse levye operandy, ne yavlyayushchiesya ssylkami,
dolzhny byt' arifmeticheskogo tipa.
Dlya ob容ktov klassa prisvaivanie v obshchem sluchae ne sovpadaet s
inicializaciej ($$R.8.4, $$R.12.1, $$R.12.6, $$R.12.8).
R.5.18 Operaciya zapyataya
Operacii zapyataya vypolnyayutsya sleva napravo.
vyrazhenie:
vyrazhenie-prisvaivaniya
vyrazhenie, vyrazhenie-prisvaivaniya
Para vyrazhenij, razdelennyh zapyatoj, vychislyaetsya sleva napravo i
znachenie levogo vyrazheniya unichtozhaetsya. Vse pobochnye effekty vychisleniya
levogo vyrazheniya mogut voznikat' do vychisleniya pravogo vyrazheniya.
Tip i znachenie rezul'tata sovpadayut s tipom i znacheniem pravogo
vyrazheniya. Rezul'tat yavlyaetsya adresom, esli takovym yavlyaetsya
pravoe vyrazhenie.
V kontekstah, gde zapyataya imeet special'noe znachenie, skazhem
v spiske fakticheskih parametrov funkcii ($$R.5.2.2) ili v spiske
inicializatorov ($$R.8.4), opisannaya zdes' operaciya zapyataya
mozhet poyavlyat'sya tol'ko v skobkah, naprimer, vyzov funkcii
f(a, (t=3,t+2), c);
soderzhit tri parametra, prichem vtoroj imeet znachenie 5.
R.5.19 Vyrazheniya-konstanty
V neskol'kih mestah opisaniya S++ trebuyutsya vyrazheniya, kotorye
dayut v rezul'tate celochislennuyu konstantu, naprimer: v zadanii granic
massiva ($$R.8.2.4), v vyrazheniyah case ($$R.6.4.2),
dlya zadaniya dliny bitovogo polya ($$R.9.6) i kak inicializiruyushchee
znachenie elementa perechisleniya ($$R.7.2).
vyrazhenie-konstanta:
vyrazhenie-usloviya
V konstrukcii vyrazhenie-konstanta mogut uchastvovat': literaly
($$R.2.5), elementy perechisleniya, znacheniya celochislennogo tipa so
specifikaciej const, inicializirovannye vyrazheniem-konstantoj
($$R.8.4) i vyrazheniya sizeof. Konstanty s plavayushchej tochkoj ($$R.2.5.3)
dolzhny byt' privedeny k celochislennomu tipu. Dopustimy tol'ko
preobrazovaniya tipa k celochislennomu tipu. V chastnosti ne dopustimy
funkcii, ob容kty klassov, ukazateli i ssylki, esli ne schitat' ih
ispol'zovaniya v sizeof. Operaciya zapyataya i operaciya prisvaivaniya
ne dopustimy v vyrazhenii-konstante.
Vse operatory, za isklyucheniem ogovorennyh sluchaev, vypolnyayutsya
odin za drugim.
operator:
pomechennyj-operator
operator-vyrazhenie
sostavnoj-operator
vybirayushchij-operator
operator-cikla
operator-perehoda
operator-opisaniya
R.6.1 Pomechennyj operator
Operator mozhno snabdit' metkoj.
pomechennyj-operator:
identifikator : operator
case vyrazhenie-konstanta : operator
default : operator
Ispol'zovanie identifikatora v kachestve metki yavlyaetsya ee opredeleniem.
Identifikator metki mozhet ispol'zovat'sya pomimo etogo tol'ko v kachestve
ukazaniya perehoda v operatore goto. Oblast'yu vidimosti metki yavlyaetsya
funkciya, v kotoroj ona poyavilas'. Metki nel'zya povtorno opisyvat'
v predelah odnoj funkcii. Nel'zya ispol'zovat' metku v operatore goto
do ee opredeleniya. Metki imeyut svoe prostranstvo imenovaniya i
oni ne vstupayut v kolliziyu s drugimi identifikatorami.
Metki v case ili default mogut vstrechat'sya tol'ko v operatore
pereklyuchatelya.
R.6.2 Operator-vyrazhenie
CHashche vsego operatorami byvayut vyrazheniya; v etom sluchae operator
imeet takoj vid:
operator-vyrazhenie:
vyrazhenie opt ;
Obychno operatory-vyrazheniya yavlyayutsya prisvaivaniyami ili vyzovami
funkcij. Vse pobochnye effekty vypolneniya operatora-vyrazheniya
proishodyat do vypolneniya sleduyushchego operatora. Operator-vyrazhenie s
otsutstvuyushchim vyrazheniem nazyvaetsya pustym operatorom. On
mozhet prigodit'sya, esli neobhodimo postavit' metku pered samym koncom
sostavnogo operatora ({) ili dlya zadaniya pustogo tela operatora
cikla while ($$R.6.5.1).
R.6.3 Sostavnoj operator ili blok
Dlya teh sluchaev, kogda vmesto odnogo operatora nuzhno ispol'zovat'
neskol'ko, predusmotren sostavnoj operator (inogda ego nazyvayut
"blok").
sostavnoj-operator:
{ spisok-operatorov opt }
spisok-operatorov:
operator
spisok-operatorov operator
Otmetim, chto opisanie schitaetsya operatorom ($$R.6.7).
R.6.4 Vybirayushchij operator
Vybirayushchie operatory vybirayut odnu iz neskol'kih struktur upravleniya.
vybirayushchij-operator:
if ( vyrazhenie ) operator
if ( vyrazhenie ) operator else operator
switch ( vyrazhenie ) operator
Operator v vybirayushchem-operatore ne mozhet byt' opisaniem.
Vyrazhenie dolzhno byt' arifmeticheskogo tipa, ili tipa ukazatelya, ili
tipa klass, dlya kotorogo sushchestvuet odnoznachnoe preobrazovanie
v arifmeticheskij tip ili tip ukazatelya ($$R.12.3).
Vychislyaetsya vyrazhenie, i esli ono imeet otlichnyj ot nulya rezul'tat,
vypolnyaetsya pervyj vlozhennyj operator. Esli ispol'zovana konstrukciya
else i vyrazhenie daet rezul'tat 0, vypolnyaetsya vtoroj vlozhennyj
operator. Neodnoznachnost' v sluchae neskol'kih konstrukciyami else
razreshaetsya putem otneseniya else k poslednemu vstretivshemusya if,
dlya kotorogo ne bylo else.
R.6.4.2 Operator pereklyuchatelya
Operator pereklyuchatelya vyzyvaet peredachu upravleniya na odin iz
neskol'kih operatorov v zavisimosti ot znacheniya vyrazheniya.
Vyrazhenie dolzhno byt' celochislennogo tipa ili tipa klassa, dlya
kotorogo sushchestvuet odnoznachnoe preobrazovanie k celochislennomu
tipu ($$R.12.3). Vypolnyayutsya standartnye celochislennye preobrazovaniya.
Lyuboj iz operatorov pereklyuchatelya mozhno pometit' odnim ili neskol'kimi
prefiksami, imeyushchimi vid:
case vyrazhenie-konstanta :
Zdes' vyrazhenie-konstanta ($$R.5.19) privoditsya k preobrazovannomu
tipu vyrazheniya pereklyuchatelya. Nikakie dve konstanty iz case odnogo
pereklyuchatelya ne dolzhny imet' odinakovoe znachenie.
V pereklyuchatele mozhet byt' tol'ko odin prefiks vida
default:
Operatory pereklyuchatelya mogut byt' vlozhennymi, togda metki iz
case ili default otnosyatsya k samomu pervomu pereklyuchatelyu,
ob容mlyushchemu ih.
Pri vypolnenii operatora pereklyuchatelya vychislyaetsya vyrazhenie,
i ego znachenie sravnivaetsya s kazhdoj iz konstant variantov (case).
Esli odna iz etih konstant ravna znacheniyu vyrazheniya, to upravlenie
peredaetsya v operator, idushchij za etoj konstantoj. Esli ni odna iz
konstant ne sovpala so znacheniem vyrazheniya, no est' prefiks
default, to upravlenie peredaetsya na operator s etim prefiksom.
Esli prefiksa default net, i sovpadeniya ne bylo, to ne vypolnyaetsya
ni odin iz operatorov pereklyuchatelya.
Esli operatory, vypolnyaemye v rezul'tate vybora, ne privodyat
k kakim-libo peredacham upravleniya, to programma prodolzhaet vypolnyat'sya
"po metkam case i default" besprepyatstvenno. Vyhod iz pereklyuchatelya
vozmozhen s pomoshch'yu operatora break (sm. $$R.6.6.1).
Obychno operator, s kotorym imeet delo pereklyuchatel', byvaet
sostavnym. Opisaniya mogut poyavit'sya v operatorah pereklyuchatelya.
Odnako perehod nizhe opisaniya, v kotorom byla yavnaya ili neyavnaya
inicializaciya, schitaetsya nezakonnym, esli tol'ko opisanie ne
nahoditsya vo vnutrennem bloke, kotoryj obhoditsya (t.e. polnost'yu
obhoditsya pri peredache upravleniya, $$R.6.7). Otsyuda sleduet,
chto opisanie s yavnoj ili neyavnoj inicializaciej dolzhno soderzhat'sya
vo vnutrennem bloke.
|ti operatory zadayut vidy cikla.
operator-cikla:
while ( vyrazhenie ) operator
do operator while (vyrazhenie)
for ( operator-inic vyrazhenie opt ; vyrazhenie opt ) operator
operator-inic:
operator-vyrazhenie
operator-opisanie
Obratite vnimanie, chto konstrukciya operator-inic konchaetsya tochkoj s
zapyatoj.
Operator v operatore-cikla ne dolzhen byt' opisaniem.
V operatore while vlozhennyj operator vypolnyaetsya do teh por,
poka znachenie vyrazheniya ne stanet ravnym nulyu. Proverka proishodit
pered kazhdym vypolneniem operatora.
Vyrazhenie dolzhno byt' arifmeticheskogo tipa, ili tipa ukazatelya, ili
tipa klass, dlya kotorogo sushchestvuet odnoznachnoe preobrazovanie v
arifmeticheskij tip ili tip ukazatelya ($$R.12.3).
V operatore do vlozhennyj operator vypolnyaetsya do teh por,
poka znachenie vyrazheniya ne stanet ravnym nulyu. Proverka proishodit
posle kazhdogo vypolneniya operatora.
Vyrazhenie dolzhno byt' arifmeticheskogo tipa, ili tipa ukazatelya,
ili tipa klass, dlya kotorogo sushchestvuet odnoznachnoe preobrazovanie
v arifmeticheskij tip ili tip ukazatelya ($$R.12.3).
Operator for
for (operator-inic vyrazhenie-1 opt ; vyrazhenie-2 opt ) operator
ekvivalenten konstrukcii
operator-inic
while (vyrazhenie-1) {
operator
vyrazhenie-2 ;
}
za isklyucheniem togo fakta, chto operator continue v operatore for
vyzovet vypolnenie vyrazhenie-2 pered tem& kak nachat' povtornoe
vychislenie vyrazheniya-1. Takim obrazom, pervyj operator zadaet
inicializaciyu dlya cikla, pervoe vyrazhenie proizvodit proverku,
vypolnyaemuyu pered kazhdym shagom cikla, tak chto cikl zavershaetsya, kogda
vyrazhenie stanovitsya nulem, a vtoroe vyrazhenie obychno zadaet
prirashchenie, i ono dobavlyaetsya posle kazhdogo shaga cikla. Pervoe
vyrazhenie dolzhno imet' arifmeticheskij tip, ili tip ukazatelya, ili
tip klassa, dlya kotorogo sushchestvuet odnoznachnoe preobrazovanie
k arifmeticheskomu tipu ili tipu ukazatelya ($$R.12.3).
Mogut byt' opushcheny odno ili oba vyrazheniya. Esli otsutstvuet
vyrazhenie-1, to ekvivalentnyj cikl s while imeet uslovie while (1).
Esli operator-inic yavlyaetsya opisaniem, oblast' vidimosti imen,
opisannyh v nem, prostiraetsya do konca bloka, zakryvayushchego operator
for.
Operatory perehoda delayut bezuslovnuyu peredachu upravleniya.
operator-perehoda:
break ;
continue ;
return vyrazhenie opt ;
goto identifikator ;
Po vyhode iz oblasti vidimosti (kakim by obrazom eto ne proizoshlo)
vyzyvayutsya destruktory ($$R.12.4) dlya vseh ob容ktov klassov,
postroennyh v etoj oblasti, kotorye eshche ne byli unichtozheny. |to
otnositsya kak k yavno opisannym ob容ktam, tak i ko vremennym ob容ktam
($$R.12.2).
Operator break mozhet vstretit'sya tol'ko v operatore cikla ili
pereklyuchatele, on privodit k okonchaniyu blizhajshego iz ob容mlyushchih
ego operatorov cikla ili pereklyuchatelej. Upravlenie peredaetsya na
operator, sleduyushchij neposredstvenno za zakanchivaemym, esli takoj est'.
R.6.6.2 Operator continue
Operator continue mozhet vstretit'sya tol'ko v operatore cikla i
privodit k peredache upravleniya v zagolovok blizhajshego
iz ob容mlyushchih operatorov cikla, t.e. v konec cikla. Bolee tochno
mozhno skazat', chto v kazhdom iz operatorov:
while (foo) { do { for (;;) {
// ... // ... // ...
contin: ; contin: ; contin: ;
} } while (foo); }
operator continue, ne otnosyashchijsya ko vneshnim operatoram cikla,
ekvivalenten operatoru goto contin.
Vozvrat iz funkcii v obrativshuyusya k nej funkciyu proishodit s pomoshch'yu
operatora return.
Operator return bez vyrazheniya mozhno ispol'zovat' tol'ko v
funkciyah, kotorye ne vozvrashchayut znachenie, t.e. v funkciyah,
vozvrashchayushchih znachenie tipa void, ili v konstruktorah ($$R.12.1)
i destruktorah ($$R.12.4). Operator return s vyrazheniem mozhno
ispol'zovat' tol'ko v funkciyah, kotorye vozvrashchayut znachenie. Znachenie
vyrazheniya peredaetsya v tu funkciyu,kotoraya vyzvala dannuyu funkciyu. Esli
nuzhno, znachenie preobrazuetsya k tipu funkcii, v kotoroj vypolnyaetsya
return, po tem zhe pravilam kak pri inicializacii. |to mozhet privesti
k vyzovu konstruktora ili kopirovaniyu vremennyh ob容ktov ($$R.12.2).
Vyhod iz funkcii po koncu ekvivalenten vozvratu bez vydavaemogo
znacheniya, chto yavlyaetsya nezakonnym dlya funkcii, vozvrashchayushchej
znachenie.
Operator goto bezuslovno peredaet upravlenie na operator,
pomechennyj identifikatorom. Identifikator dolzhen byt' metkoj
($$R.6.1), nahodyashchejsya v tekushchej funkcii.
Operator opisaniya zavodit v bloke novyj identifikator i imeet
vid:
operator-opisaniya:
opisanie
Esli identifikator, vvedennyj s pomoshch'yu opisaniya, uzhe byl ranee
opisan vo vneshnem bloke, vneshnee opisanie stanovitsya skrytym do
konca bloka, posle chego ono opyat' vstupaet v silu.
Vse inicializacii avtomaticheskih (auto) i registrovyh (register)
peremennyh proizvodyatsya kazhdyj raz, kogda vypolnyaetsya
operator-opisanie. Unichtozhenie lokal'nyh peremennyh, opisannyh v
bloke, proishodit pri vyhode iz bloka ($$R.6.6). Unichtozhenie
avtomaticheskih peremennyh, opredelennyh v cikle, proishodit
na kazhdom shage cikla. Naprimer, peremennaya Index j sozdaetsya i
unichtozhaetsya kazhdyj raz v techenie cikla po i:
for (int i = 0; i<100; i++)
for (Index j = 0; j<100; j++) {
// ...
}
Vyhod iz cikla ili iz bloka ili perehod, minuya inicializaciyu
avtomaticheskih peremennyh, privodit k unichtozheniyu avtomaticheskih
peremennyh, opisannyh v tochke, otkuda proishodit perehod, no ne
v tochke, kuda proishodit perehod.
Perehod v blok vozmozhen pri uslovii, chto on ne privodit k
propusku inicializacii. Schitaetsya nezakonnym perehod, obhodyashchij
opisanie s yavnoj ili neyavnoj inicializaciej, krome sluchaev, kogda
ono nahoditsya vo vnutrennem bloke, kotoryj propuskaetsya (t.e. v nego
nikogda ne popadaet upravlenie) ili perehod proishodit iz toj tochki,
gde uzhe byla inicializaciya peremennoj. Naprimer,
void f()
{
// ...
goto lx; //oshibka: perehod, minuya inicializaciyu
// ...
ly:
X a = 1;
// ...
lx:
goto ly; // normal'no, za perehodom budet vyzov
// destruktora dlya `a'
}
Avtomaticheskaya peremennaya, kotoraya byla sozdana pri nekotorom
uslovii, unichtozhaetsya pri vypolnenii etogo usloviya, i ne mozhet
byt' dostupna vne proverki etogo usloviya. Naprimer,
if (i)
for (int j = 0; j<100; j++) {
// ...
}
if (j!=100) // oshibka: obrashchenie vne usloviya
// ...
;
Inicializaciya lokal'nogo ob容kta s klassom pamyati static ($$R.7.1.1)
proizvoditsya prezhde, chem upravlenie projdet cherez oblast' ego
opisaniya. Esli staticheskaya peremennaya inicializiruetsya vyrazheniem,
kotoroe ne yavlyaetsya vyrazheniem-konstantoj, to pered pervym vhodom
v blok proishodit standartnaya inicializaciya nulem, privedennym
k nuzhnomu tipu ($$R.8.4).
Destruktor dlya lokal'nogo staticheskogo ob容kta budet vyzyvat'sya
v tom i tol'ko v tom sluchae, esli peremennaya byla sozdana s pomoshch'yu
konstruktora. Destruktor dolzhen vyzyvat'sya srazu pered vyzovom ili
kak sostavnaya chast' vyzova funkcij, zadannyh v atexit() ($$R.3.4).
R.6.8 Razreshenie neodnoznachnosti
Sushchestvuet neodnoznachnost' v grammatike yazyka, kasayushchayasya
operatora-vyrazheniya i opisaniya, a imenno, operator-vyrazhenie,
soderzhashchij kak samoe levoe podvyrazhenie yavnoe preobrazovanie tipa,
zadannoe v funkcional'nom stile ($$R.5.2.3), mozhet byt' ne otlichim ot
opisaniya, v kotorom pervyj opisatel' nachinaetsya so (. V takih sluchayah
operator schitaetsya opisaniem.
Dlya razresheniya neodnoznachnosti sleduet issledovat' ves' operator,
chtoby opredelit' yavlyaetsya on operatorom-vyrazheniem ili opisaniem.
Tak ustranyaetsya neodnoznachnost' vo mnogih sluchayah. Naprimer, pust'
T - imya-prostogo-tipa ($$R.7.1.6), togda imeem
T(a)->m = 7; // operator-vyrazhenie
T(a)++; // operator-vyrazhenie
T(a,5)<<c; // operator-vyrazhenie
T(*e)(int); // opisanie
T(f)[]; // opisanie
T(g) = {1, 2 }; // opisanie
T(*d)(double(3)); // opisanie
Ostal'nye sluchai predstavlyayut opisaniya. Naprimer,
T(a); // opisanie
T(*b)(); // opisanie
T(c)=7; // opisanie
T(d),e,f=3; // opisanie
T(g)(h,2); // opisanie
Neodnoznachnost' zdes' chisto sintaksicheskaya, t.e. na ee
razreshenie ne vliyaet tot fakt, yavlyaetsya li imya imenem-tipa ili net.
Est' drugoj vid kollizii mezhdu operatorom-vyrazheniem i opisaniem,
kotoryj razreshaetsya trebovaniem, chtoby opisanie funkcii v bloke
($$R.6.3) soprovozhdalos' imenem-tipa, naprimer:
void g()
{
int f(); // opisanie
int a; // opisanie
f(); // operator-vyrazhenie
a; // operator-vyrazhenie
}
Opisaniya ispol'zuyutsya dlya interpretacii kazhdogo iz identifikatorov;
neobyazatel'no, chtoby oni soprovozhdalis' vydeleniem pamyati,
sopostavlyaemoj s identifikatorom. Opisaniya imeyut vid
opisaniya:
specifikacii-opisaniya opt spisok-opisatelej opt ;
opisanie-asm
opredelenie-funkcii
specifikaciya-svyazi
Opisateli v spiske-opisatelej ($$R.8) soderzhat opisyvaemye
identifikatory. Konstrukciya specifikacii-opisaniya mozhet otsutstvovat'
tol'ko v opredelenii funkcij ($$R.8.3) ili v opisanii funkcij.
Spisok-opisatelej mozhet byt' pustym, tol'ko pri opisanii klassa ($$R.9)
ili perechisleniya ($$R.7.2), t.e. kogda specifikaciya-opisaniya est'
specifikaciya-klassa ili specifikaciya-perechisleniya.
Konstrukciya opisanie-asm ob座asnyaetsya v $$R.7.3, a specifikaciya-svyazi
v $$R.7.4. Opisanie proishodit v opredelennoj oblasti vidimosti
($$R.3.2), pravila oblasti vidimosti privodyatsya v $$R.10.4.
V opisanii mozhno ispol'zovat' sleduyushchie specifikacii:
specifikaciya-opisaniya:
specifikaciya-klassa-pamyati
specifikaciya-tipa
specifikaciya-fct
specifikaciya-shablona-tipa
friend
typedef
specifikacii-opisaniya:
specifikacii-opisaniya opt specifikaciya-opisaniya
Samaya dlinnaya posledovatel'nost' konstrukcij specifikaciya-opisaniya,
kotoraya, vozmozhno, yavlyaetsya imenem tipa, obrazuet v opisanii konstrukciyu
specifikacii-opisaniya. Posledovatel'nost' dolzhna byt' soglasovannoj,
chto ob座asnyaetsya nizhe. Naprimer,
typedef char* Pc;
static Pc; // oshibka: net imeni
Zdes' opisanie static Pc yavlyaetsya nezakonnym, poskol'ku ne ukazano
nikakogo imeni staticheskoj peremennoj tipa Pc. CHtoby imet'
peremennuyu tipa int s imenem Pc, neobhodimo zadat'
specifikaciyu-tipa int, chtoby pokazat', chto (pere)opredelyaetsya
imya Pc iz typedef, a ne prosto Pc yavlyaetsya odnim iz elementov
posledovatel'nosti konstrukcij specifikaciya-opisaniya, naprimer,
void f(const Pc); // void f(char* const)
void g(const int Pc); // void g(const int)
Ukazhem, chto poskol'ku signed, unsigned, long i short po
umolchaniyu traktuyutsya kak int, konstrukciya imya-typedef, kotoraya
poyavlyaetsya posle odnoj iz perechislennyh specifikacij tipa,
dolzhna zadavat' (pere)opredelyaemoe imya, naprimer,
void h(unsigned Pc); // void h(unsigned int)
void k(unsigned int Pc); // void k(unsigned int)
R.7.1.1 Specifikacii klassa pamyati
Specifikacii klassa pamyati mogut byt' takie:
specifikaciya-klassa-pamyati:
auto
register
static
extern
Specifikacii auto i register mogut primenyat'sya tol'ko dlya
imen ob容ktov, kotorye opisany v bloke ($$R.6.3), ili dlya formal'nyh
parametrov ($$R.8.3). Pochti vsegda specifikaciya auto izbytochna i
ispol'zuetsya ne chasto, tak, auto ispol'zuetsya, chtoby yavno otdelit'
operator-opisanie ot operatora-vyrazheniya ($$R.6.2).
Opisanie register yavlyaetsya opisaniem auto, kotoroe podskazyvaet
translyatoru, chto opisyvaemye peremennye budut ispol'zovat'sya
dostatochno intensivno. Podskazka mozhet byt' proignorirovana, i vo
mnogih realizaciyah ona ignoriruetsya v tom sluchae, kogda beretsya
adres peremennoj.
Opisanie ob容kta schitaetsya opredeleniem, esli tol'ko ono ne
soderzhit specifikacii extern i inicializacii ($$R.3.1).
Opredelenie privodit k vydeleniyu pamyati sootvetstvuyushchego
razmera i vypolneniyu sootvetstvuyushchej inicializacii ($$R.8.4).
Specifikacii static i extern mogut primenyat'sya tol'ko k imenam
ob容ktov ili funkcij ili k anonimnym ob容dineniyam. Vnutri bloka
nedopustimy opisaniya funkcij so specifikaciej static ili
formal'nyh parametrov so specifikaciej static ili extern.
Staticheskie chleny klassa opisyvayutsya v $$R.9.4. Specifikaciya
extern nedopustima dlya chlenov klassa.
Imya so specifikaciej static podlezhit vnutrennemu svyazyvaniyu.
Ob容kty, opisannye kak const, podlezhat vnutrennemu svyazyvaniyu,
esli tol'ko oni ne byli opisany s vneshnej svyaz'yu. Imya so
specifikaciej extern podlezhit vneshnemu svyazyvaniyu, esli tol'ko ranee
ono ne bylo opisano s vnutrennej svyaz'yu. Imya s fajlovoj oblast'yu
vidimosti i bez specifikacii-klassa-pamyati podlezhit vneshnemu
svyazyvaniyu, esli tol'ko ranee ono ne bylo opisano s vnutrennej
svyaz'yu ili so specifikaciej const. V smysle svyazyvaniya dlya funkcij,
ne yavlyayushchihsya chlenami, specifikaciya inline ekvivalentna static
($$R.3.3). Dlya odnogo imeni vse ego specifikacii, opredelyayushchie
svyazyvanie, dolzhny byt' soglasovany. Naprimer,
static char* f(); // f() imeet vnutrennee svyazyvanie
char* f() // f() vse eshche vnutrennee
{ /* ... */ }
char* g(); // g() imeet vneshnee svyazyvanie
static char* g() // oshibka: protivorechie v svyazyvanii
{ /* ... */ }
static int a; // `a' imeet vnutrennee svyazyvanie
int a; // oshibka: vtoroe opredelenie
static int b; // `b' imeet vnutrennee svyazyvanie
extern int b; // `b' vse eshche vnutrennee
int c; // `c' imeet vneshnee svyazyvanie
static int c; // oshibka: protivorechie v svyazyvanii
extern int d; // `d' imeet vneshnee svyazyvanie
static int d; // oshibka: protivorechie v svyazyvanii
Imya neopredelennogo klassa mozhno ispol'zovat' v opisanii
extern. Odnako, takoe opisanie nel'zya ispol'zovat' prezhde, chem
klass budet opredelen, naprimer,
struct S;
extern S a;
extern S f();
extern void g(S);
void h()
{
g(a); // oshibka: S neopredeleno
f(); // oshibka: S neopredeleno
}
R.7.1.2 Specifikacii funkcij
Nekotorye specifikacii mozhno ispol'zovat' tol'ko v opisanii funkcij.
specifikaciya-fct:
inline
virtual
Specifikaciya inline podskazyvaet translyatoru, chto neobhodimo
proizvesti podstanovku tela funkcii vmesto obychnoj realizacii
vyzova funkcii. Podskazka mozhet ignorirovat'sya. V sluchae funkcij,
ne yavlyayushchihsya chlenami, specifikaciya inline dopolnitel'no ustanavlivaet
dlya funkcii vnutrennee svyazyvanie ($$R.3.3). Funkciya ($$R.5.2.2,
$$R.8.2.5), opredelennaya v opisanii klassa, imeet po umolchaniyu
specifikaciyu inline.
Funkciya-chlen so specifikaciej inline dolzhna imet' v tochnosti
takoe zhe opredelenie v kazhdoj edinice translyacii, gde ona poyavlyaetsya.
Funkciyu-chlen ne obyazatel'no yavno opisyvat' so specifikaciej
inline pri opisanii klassa, chtoby ona traktovalas' kak podstanovka.
Esli specifikacii inline ne bylo, svyazyvanie budet vneshnim,
esli tol'ko opredelenie so specifikaciej inline ne poyavitsya pered
pervym vyzovom funkcii.
class X {
public:
int f();
inline int g(); // X::g() imeet vnutrennee svyazyvanie
int h();
};
void k(X* p)
{
int i = p->f(); // teper' X::f() vneshnee svyazyvanie
int j = p->g();
// ...
}
inline int X::f() // oshibka: vyzov do opredeleniya
// kak inline
{
// ...
}
inline int X::g()
{
// ...
}
inline int X::h() // teper' X::h() imeet vnutrennee svyazyvanie
{
// ...
}
Specifikaciya virtual mozhet ispol'zovat'sya tol'ko v opisaniyah
nestaticheskih funkcij-chlenov pri opisanii klassa (sm. $$R.10.2).
R.7.1.3 Specifikaciya typedef
Opisaniya so specifikaciej typedef zadayut identifikatory, kotorye
pozdnee mogut ispol'zovat'sya dlya oboznacheniya osnovnyh ili
proizvodnyh tipov. Specifikaciya typedef nedopustima v opredelenii-funkcii
($$R.8.3).
imya-typedef:
identifikator
V predelah oblasti vidimosti ($$R.3.2) opisaniya typedef lyuboj
identifikator, poyavlyayushchijsya v chasti lyubogo iz opisatelej,
stanovitsya sintaksicheski ekvivalentnym sluzhebnomu slovu i oboznachaet tip,
svyazannyj s dannym identifikatorom, kak opisano v $$R.8. Takim obrazom,
imya-typedef yavlyaetsya sinonimom drugogo tipa. V otlichie ot opisaniya
klassa ($$R.9.1) imya-typedef ne dobavlyaet novogo tipa. Naprimer,
posle opisaniya
typedef int MILES, *KLICKSP;
konstrukcii
MILES distance;
extern KLICKSP metricp;
yavlyayutsya zakonnymi opisaniyami, tip distance est' int, a u metricp
tip "ukazatel' na int".
S pomoshch'yu typedef mozhno pereopredelit' imya tak, chtoby ono opyat'
oboznachalo tip, na kotoryj uzhe ssylalos', prichem dazhe v toj oblasti
vidimosti, v kotoroj tip byl pervonachal'no opisan, naprimer,
typedef struct s { /* ... */ } s;
typedef int I;
typedef int I;
typedef I I;
Bezymyannyj klass, kotoryj opredelyaetsya v typedef, poluchaet v
kachestve svoego imeni imya, ispol'zovannoe v typedef, naprimer,
typedef struct { /* .... */ } S; // imya struktury stalo S
S pomoshch'yu opisaniya typedef nel'zya pereopredelit' imya tipa,
opisannogo v etoj zhe oblasti vidimosti, tak, chtoby ono oboznachalo
drugoj tip, naprimer,
class complex { /* ... */ };
typedef int complex; // oshibka: pereopredelenie
Analogichno, nel'zya opisyvat' klass s imenem tipa, opisannogo
v etoj zhe oblasti vidimosti, tak, chtoby on oboznachal drugoj
tip, naprimer,
typedef int complex;
class complex { /* ... */ }; // oshibka: pereopredelenie
Imya-typedef, kotoroe oboznachaet klass, yavlyaetsya imenem-klassa
($$R.9.1). Sinonim nel'zya ispol'zovat' posle sleduyushchih prefiksov:
class, struct i union, a takzhe v imenah konstruktorov i
destruktorov v opisanii samogo klassa, naprimer,
struct S {
S();
~S();
};
typedef struct S T;
S a = T(); // normal'no
struct T* p; // oshibka
R.7.1.4 Specifikaciya shablona tipa
Specifikaciya shablona tipa ispol'zuetsya dlya zadaniya semejstva tipov
ili funkcij (sm. $$R.14).
R.7.1.5 Specifikaciya friend
Specifikaciya friend ispol'zuetsya dlya zadaniya dostupa k chlenam klassa
(sm. $$R.11.4).
R.7.1.6 Specifikaciya tipa
K specifikacii tipa otnosyatsya:
specifikaciya-tipa:
imya-prostogo-tipa
specifikaciya-klassa
specifikaciya-perechisleniya
specifikaciya-slozhnogo-tipa
:: imya-klassa
const
volatile
Pri opisanii ob容kta sluzhebnye slova const i volatile mozhno dobavit'
k lyuboj zakonnoj specifikacii-tipa. Vo vseh drugih sluchayah v opisanii
mozhet prisutstvovat' ne bolee odnoj specifikacii-tipa. Ob容kt so
specifikaciej const mozhno inicializirovat', no ego znachenie ne
dolzhno izmenyat'sya v dal'nejshem. Ob容kt so specifikaciej const, esli
tol'ko on ne byl yavno opisan kak extern, ne podlezhit vneshnemu
svyazyvaniyu i dolzhen inicializirovat'sya ($$R.8.4, $$R.12.1). Celoe
so specifikaciej const, inicializirovannoe vyrazheniem-konstantoj,
mozhet ispol'zovat'sya v vyrazhenii-konstante ($$R.5.19). Kazhdyj
element massiva so specifikaciej const imeet tu zhe specifikaciyu,
a kazhdyj nestaticheskij chlen, ne yavlyayushchijsya funkciej, iz ob容kta klassa
so specifikaciej const sam schitaetsya const ($$R.9.3.1). Ob容kt tipa
bez konstruktora ili destruktora, kotoryj imeet specifikaciyu const,
mozhet byt' pomeshchen v pamyat', dostupnuyu tol'ko po chteniyu. Popytka
zapisi v lyubuyu chast' takogo ob容kta ili privedet k osoboj adresnoj
situacii, ili projdet bessledno, kak esli by ob容kt ne imel
specifikacii const.
Ne sushchestvuet ne zavisyashchego ot realizacii ob座asneniya ob容ktov so
specifikaciej volatile. Ona sluzhit podskazkoj translyatoru izbegat'
slishkom aktivnoj optimizacii, svyazannoj s etim ob容ktom, poskol'ku
znachenie ob容kta mozhet izmenyat'sya sposobami, skrytymi ot
translyatora. Kazhdyj element massiva so specifikaciej volatile
imeet tu zhe specifikaciyu i kazhdyj nestaticheskij chlen, ne yavlyayushchijsya
funkciej, iz ob容kta klassa so specifikaciej volatile sam schitaetsya
volatile ($$R.9.3.1).
Esli specifikaciya-tipa otsutstvuet v opisanii, ona schitaetsya
zadannoj kak int.
imya-prostogo-tipa:
polnoe-imya-klassa
utochnennoe-imya-tipa
char
short
int
long
signed
unsigned
float
double
void
Vmeste s int nel'zya zadavat' bolee odnogo sluzhebnogo slova long
ili short. Oni mogut ispol'zovat'sya i poodinochke, togda schitaetsya,
chto tip est' int. Sluzhebnoe slovo long mozhet poyavit'sya vmeste s
double. Vmeste s char, short, int ili long nel'zya zadavat' bolee
odnogo sluzhebnogo slova signed ili unsigned. Oni mogut
ispol'zovat'sya i poodinochke, togda schitaetsya, chto tip est' int.
Specifikaciya signed ukazyvaet, chto ob容kty tipa char i bitovye
polya yavlyayutsya znakovymi, dlya drugih celochislennyh tipov eta
specifikaciya izbytochna.
Konstrukcii specifikaciya-klassa i specifikaciya-perechisleniya
opredelyayutsya v $$R.9 i $$R.7.2 sootvetstvenno.
specifikaciya-slozhnogo-tipa:
sluzhebnoe-slovo-klassa imya-klassa
sluzhebnoe-slovo-klassa identifikator
sluzhebnoe-slovo-klassa:
class
struct
union
Esli zadan identifikator, specifikaciya-slozhnogo-tipa opisyvaet
ego kak imya-klassa (sm. $$R.9.1).
Esli opredeleno imya, kotoroe opisyvaetsya s pomoshch'yu specifikacii
union, to ono dolzhno byt' opredeleno kak ob容dinenie. Esli opredeleno
imya, kotoroe opisyvaetsya s pomoshch'yu specifikacii class, to ono dolzhno
byt' opredeleno s pomoshch'yu specifikacij class ili struct. Esli
opredeleno imya, kotoroe opisyvaetsya s pomoshch'yu specifikacii struct,
ono dolzhno byt' opredeleno s pomoshch'yu specifikacii class ili
struct. Imena vlozhennyh tipov ($$R.9.7) dolzhny utochnyat'sya imenem
ob容mlyushchego klassa:
utochnennoe-imya-tipa:
imya-typedef
imya-klassa :: utochnennoe-imya-tipa
polnoe-imya-klassa:
utochnennoe-imya-klassa
:: utochnennoe-imya-klassa
utochnennoe-imya-klassa:
imya-klassa
imya-klassa :: utochnennoe-imya-klassa
Imya, utochnennoe imenem-klassa dolzhno byt' tipom, opredelennym v
etom klasse ili v bazovom klasse etogo klassa. Kak obychno, imya,
opisannoe v proizvodnom klasse, delaet nevidimymi chleny s etim
imenem iz bazovyh klassov (sm. $$R.3.2).
R.7.2 Opisanie perechisleniya
Perechislenie yavlyaetsya otdel'nym celochislennym tipom ($$R.3.6.1)
s konstantami-imenami. Ego imya v svoej oblasti vidimosti stanovitsya
konstrukciej imya-perechisleniya, t.e. sluzhit zarezervirovannym slovom.
imya-perechisleniya:
identifikator
specifikaciya-perechisleniya:
enum identifikator opt { spisok-perechisleniya }
spisok-perechisleniya:
element-perechisleniya
spisok-perechisleniya , element-perechisleniya
element-perechisleniya:
identifikator
identifikator = vyrazhenie-konstanta
Vse identifikatory iz spiska-perechisleniya schitayutsya opisannymi
kak konstanty i mogut poyavlyat'sya vsyudu, gde trebuyutsya konstanty.
Esli ne bylo elementov perechisleniya s =, to znacheniya konstant
nachinayutsya s nulya i posledovatel'no uvelichivayutsya na edinicu
po mere prodvizheniya v spiske sleva napravo. Esli element
perechisleniya vstretilsya s =, to ego identifikator prinimaet zadannoe
znachenie, a posleduyushchie identifikatory bez inicializiruyushchej chasti
budut poluchat' vozrastayushchie znacheniya, nachinaya s zadannogo. Znachenie
elementa perechisleniya dolzhno byt' tipa int ili znacheniem, kotoroe
mozhno privesti k int s pomoshch'yu standartnyh celochislennyh
preobrazovanij ($$R.4.1).
Imena elementov perechisleniya dolzhny byt' otlichny ot imen obychnyh
peremennyh i drugih elementov perechisleniya toj zhe oblasti
vidimosti. Znacheniya elementov perechisleniya ne obyazany otlichat'sya
drug ot druga. Schitaetsya, chto element perechisleniya opisan s momenta
poyavleniya ego identifikatora ili inicializiruyushchego znacheniya,
(esli ono est'). Naprimer, v opredeleniyah
enum { a, b, c=0 };
enum { d, e, f=e+2 };
znacheniya a, c, i d zadany kak 0, b i e kak 1, a f kak 3.
Kazhdoe perechislenie yavlyaetsya celochislennym tipom, kotoryj
otlichen ot vseh drugih celochislennyh tipov. Tipom elementa perechisleniya
schitaetsya dannoe perechislenie. Znachenie elementa perechisleniya ili
ob容kta tipa perechisleniya preobrazuetsya k celomu s pomoshch'yu
standartnyh celochislennyh preobrazovanij ($$R.4.1). Naprimer,
v sleduyushchem fragmente:
enum color { red, yellow, green=20, blue };
color col = red;
color* cp = &col;
if (*cp == blue ) // ...
color zadan kak celochislennyj tip, opisyvayushchij raznye cveta,
col opisan kak ob容kt etogo tipa, a cp kak ukazatel' na ob容kt
etogo tipa. Vozmozhnymi znacheniyami ob容kta tipa color yavlyayutsya
red, yellow, green, blue. |ti znacheniya mozhno preobrazovat'
v celye znacheniya 0, 1, 20 i 21. Poskol'ku kazhdoe perechislenie - eto
otdel'nyj tip, ob容ktu tipa color mozhno prisvaivat' tol'ko znacheniya
tipa color, naprimer,
color c = 1; // oshibka: nesootvetstvie tipov
// net preobrazovaniya ot int v color
int i = yellow; // normal'no: yellow preobrazuetsya v int so znacheniem 1
// standartnoe celochislennoe preobrazovanie
Obratites' takzhe k $$R.18.3.
|lementy perechisleniya, opredelennye v klasse ($$R.9), otnosyatsya
k oblasti vidimosti etogo klassa, i k nim mozhno obrashchat'sya izvne
funkcij-chlenov etogo klassa tol'ko s pomoshch'yu yavnogo utochneniya
imenem klassa ($$R.5.1). Imya samogo tipa perechisleniya lokal'no
v etom klasse ($$R.9.7), naprimer,
class X {
public:
enum direction { left='l', right='r' };
int f(int i)
{ return i==left ? 0 : i==right ? 1 : 2; }
};
void g(X* p)
{
direction d; // oshibka: `direction' vne
int i; // oblasti vidimosti
i = p->f(left); // oshibka: `left' tozhe nevidim
i = p->f(X::right); // normal'no
// ...
}
Opisanie asm imeet vid:
opisanie-asm:
asm ( stroka-literal) ;
Naznachenie opisaniya asm opredelyaetsya realizaciej. Obychno ono
ispol'zuetsya dlya peredachi informacii ot translyatora k assembleru.
R.7.4 Specifikacii svyazi
S pomoshch'yu specifikacii-svyazi mozhno svyazat' ($$R.3.3) fragmenty
programm na S++ i na drugom yazyke:
specifikaciya-svyazi:
extern stroka-literal { spisok-opisanij opt }
extern stroka-literal opisanie
spisok-opisanij:
opisanie
spisok-opisanij opisanie
Trebuemoe svyazyvanie zadaetsya s pomoshch'yu stroki-literala. Ee naznachenie
opredelyaetsya realizaciej. No vo vseh realizaciyah dolzhno byt'
predusmotreno svyazyvanie s funkciej na yazyke S ("S") i s funkciej
na yazyke S++ ("S++"). Po umolchaniyu svyazyvanie zadaetsya kak "S++",
naprimer,
complex sqrt(complex); // po umolchaniyu svyazyvanie s C++
extern "C" {
double sqrt(double); // svyazyvanie s C
}
Specifikacii svyazi mogut byt' vlozhennymi. Specifikaciya svyazi
ne zadaet oblast' vidimosti. Specifikaciya-svyazi mozhet vstretit'sya
tol'ko v fajlovoj oblasti vidimosti ($$R.3.2). Specifikaciya-svyazi
dlya klassa otnositsya k ob容ktam, opisannym v nem, i funkciyam, ne
yavlyayushchimsya chlenami. Specifikaciya-svyazi, otnosyashchayasya k nekotoroj
funkcii, otnositsya i ko vsem ob容ktam i funkciyam, opisannym v nej.
Opisanie svyazi, soderzhashchee neizvestnuyu dlya realizacii stroku,
schitaetsya oshibochnym.
Esli funkciya imeet bolee odnoj specifikacii-svyazi, to oni dolzhny
byt' soglasovany, t.e. zadavat' odnu i tu zhe stroku-literal.
Opisanie funkcii bez ukazaniya specifikacii-svyazi ne dolzhno
predshestvovat' pervomu ukazaniyu specifikacii svyazi dlya etoj funkcii.
Funkciya mozhet byt' opisana bez ukazaniya specifikacii svyazi dazhe
posle yavnogo ukazaniya specifikacii svyazi, no svyazyvanie, yavno zadannoe
v bolee rannem opisanii, ne budet ustraneno takim opisaniem funkcii.
Iz mnozhestva peregruzhennyh funkcij ($$R.13) s dannym imenem
ne bolee odnoj mozhet imet' svyazyvanie s yazykom S, sm. $$R.7.4.
Svyazyvanie mozhno ustanovit' dlya ob容ktov, naprimer:
extern "C" {
// ...
_iobuf_iob[_NFILE];
// ...
int _flsbuf(unsigned,_iobuf*);
// ...
}
Kogda zadaetsya specifikaciya svyazi, to funkcii i ob容kty mozhno opisat' kak
staticheskie vnutri { }. Dlya takih funkcij ili ob容ktov komanda
svyazyvaniya ignoriruetsya. Inache, funkciya, opisannaya pri zadanii svyazi,
traktuetsya, kak esli by ona byla yavno opisana kak extern, naprimer,
nizhe vtoroe opisanie oshibochno ($$R.7.1.1):
extern "C" double f();
static double f(); // oshibka
Ob容kt, opisannyj vnutri konstrukcii
extern "C" { /* ... */ }
vse zhe schitaetsya opredelennym, a ne prosto opisannym.
Svyazyvanie ob容ktov na S++ s ob容ktami, opredelennymi na drugih
yazykah, tak zhe kak i obratnoe svyazyvanie, zavisit ot yazykov i
realizacii. Takoe svyazyvanie vozmozhno tol'ko v tom sluchae, kogda
algoritmy razmeshcheniya ob容ktov v pamyati yavlyayutsya dostatochno shozhimi
dlya dvuh yazykov.
Esli dlya zadaniya svyazi v stroke-literale iz specifikacii-svyazi
ispol'zuetsya imya yazyka programmirovaniya, to rekomenduetsya, chtoby
napisanie etogo imeni kopirovalos' iz dokumenta, opredelyayushchego dannyj
yazyk, naprimer, Ada (a ne ADA) i Fortran (a ne FORTRAN).
Spisok-opisatelej, figuriruyushchij v opisanii, - eto posledovatel'nost'
cherez zapyatuyu opisatelej, kazhdyj iz kotoryh mozhet imet'
inicializator.
spisok-opisanij:
opisatel'-s-inicializatorom
spisok-opisanij , opisatel'-s-inicializatorom
opisatel'-s-inicializatorom:
opisatel' inicializator opt
Opisanie sostoit iz dvuh chastej: specifikacii (specifikaciya-opisaniya;
sm. $$R.7.1) i opisatelej (spisok-opisatelej). Specifikacii zadayut
osnovnoj tip, klass pamyati ili drugie svojstva opisyvaemyh ob容ktov
i funkcij. Opisateli zadayut imya etih ob容ktov i funkcij, a takzhe,
vozmozhno, izmenyayut tip s pomoshch'yu takih operacij, kak * (ukazatel' na)
i () (funkciya vozvrashchayushchaya). V opisatele takzhe mozhno zadat' nachal'nye
znacheniya, inicializaciya obsuzhdaetsya v $$R.8.4 i $$R.12.6.
Opisateli imeyut takoj sintaksis:
opisatel':
imya-v-opisatele
operaciya-ptr opisatel'
opisatel' (spisok-opisanij-parametrov) spisok-specifikacij-cv opt
opisatel' [ vyrazhenie-konstanta opt]
( opisatel' )
operaciya-ptr:
* spisok-specifikacij-cv opt
& spisok-specifikacij-cv opt
polnoe-imya-klassa :: * spisok-specifikacij-cv opt
spisok-specifikacij-cv:
const
volatile
imya-v-opisatele:
imya
imya-klassa
~imya-klassa
imya-typedef
utochnennoe-imya-tipa
Konstrukciya imya-klassa imeet opredelennoe naznachenie pri opisanii
klassa s etim imenem, ona zhe ispol'zuetsya kak utochnenie v operacii ::
dlya razresheniya kollizij v oblasti vidimosti ($$R.12.1, $$R.12.4).
Imya tipa neobhodimo ukazyvat' pri zadanii operacii yavnogo
preobrazovaniya tipa ili v kachestve parametra v operaciyah sizeof
ili new. Dlya etogo sluzhit konstrukciya imya-tipa, kotoraya sintaksicheski
ekvivalentna opisaniyu ob容kta ili funkcii etogo tipa, v kotorom
otsutstvuet imya ob容kta ili funkcii.
imya-tipa:
spisok-specifikacij-tipa abstraktnyj-opisatel' opt
spisok-specifikacij-tipa:
specifikaciya-tipa spisok-specifikacij-tipa
abstraktnyj-opisatel':
operaciya-ptr abstraktnyj-opisatel' opt
abstraktnyj-opisatel' opt ( spisok-opisanij-parametrov ) spisok-specifikacij cv opt
abstraktnyj-opisatel' opt [ vyrazhenie-konstanta opt ]
( abstraktnyj-opisatel' )
Mozhno odnoznachno ukazat', v kakom meste abstraktnogo-opisatelya
nuzhno dobavit' identifikator, chtoby konstrukciya stala opisatelem,
dopustimym v opisanii. Togda poimenovannyj tip budet tem zhe, chto i
tip gipoteticheskogo identifikatora. Naprimer, opisaniya
int // int i
int * // int *pi
int *[3] // int *p[3]
int (*)[3] // int (*p3i)[3]
int *() // int *f()
int (*)(double) // int (*pf)(double)
zadayut sootvetstvenno takie tipy: "celoe", "ukazatel' na celoe",
"massiv iz 3 ukazatelej na celoe", "ukazatel' na massiv iz 3 celyh",
"funkciya bez parametrov, vozvrashchayushchaya ukazatel' na celoe",
"ukazatel' na funkciyu s parametrom tipa double, vozvrashchayushchuyu celoe".
R.8.1.1 Ustranenie neodnoznachnosti
Neodnoznachnost', otmechennaya v $$R.6.8, kotoraya voznikaet iz-za shodstva
mezhdu privedeniem, zadannym v funkcional'nom stile, i opisaniem,
mozhet takzhe poyavit'sya v kontekste opisaniya. V etom kontekste ona
proyavlyaetsya kak shodstvo mezhdu opisaniem funkcii, v kotorom est'
izbytochnye skobki vokrug imeni parametra, i opisaniem ob容kta, v
kotorom v kachestve inicializatora ispol'zuetsya operaciya privedeniya,
zadannaya v funkcional'nom stile. Kak i dlya operatorov, neodnoznachnost'
ustranyaetsya pravilom, soglasno kotoromu sleduet schitat' opisaniem lyubuyu
konstrukciyu, kotoraya mozhet sluzhit' takovym. Mozhno yavno ustranit'
neodnoznachnost' v opisanii ili s pomoshch'yu privedeniya, zadannogo ne v
funkcional'nom stile, ili s pomoshch'yu operacii = dlya oboznacheniya
inicializacii, naprimer,
struct S {
S(int);
};
void foo(double a)
{
S x(int(a)); // opisanie funkcii
S y((int)a); // opisanie ob容kta
S z = int(a); // opisanie ob容kta
}
Spisok opisatelej sleduet posle (vozmozhno pustogo) spiska
specifikacij-opisaniya ($$R.7.1). Kazhdyj opisatel' soderzhit v tochnosti
odno imya-iz-opisatelya, kotoroe zadaet opisyvaemyj identifikator.
Esli ne schitat' opisanij nekotoryh special'nyh funkcij ($$R.12.3,
$$R.13.4), imya-iz-opisatelya yavlyaetsya prosto identifikatorom.
Specifikacii auto, static, extern, register, friend, inline, virtual
ili typedef otnosyatsya neposredstvenno k kazhdomu imeni-iz-opisatelya iz
spiska opisatelej. Tip kazhdogo imeni-iz-opisatelya opredelyaetsya kak
specifikaciej-opisaniya ($$R.7.1), tak i ego opisatelem.
Takim obrazom, opisanie nekotorogo identifikatora imeet vid
T D
gde T oboznachaet tip, a D - opisatel'. Esli v opisanii D est'
identifikator bez skobok, to tip etogo identifikatora est' T.
V opisanii, gde D imeet vid
( D1 )
tip D1 takoj zhe, kak i tip D. Nalichie skobok ne menyaet tipa zaklyuchennogo
v nih imeni-iz-opisatelya, no dlya slozhnyh opisatelej ono mozhet povliyat'
na poryadok primeneniya operacij.
V opisanii T D, v kotorom D imeet vid
* spisok-specifikacij-cv opt D1
tip opisyvaemogo identifikatora est'
"... spisok-specifikacij-cv ukazatel' na T". Konstrukciya
spisok-specifikacij-cv otnositsya k ukazatelyu, a ne k ukazuemomu
ob容ktu.
Naprimer, v opisaniyah
const ci = 10, *pc = &ci, *const cpc = pc;
int i *p, *const cp = &i;
opredelyayutsya: ci kak konstanta celoe; pc kak ukazatel' na konstantu
celoe; cpc kak konstanta ukazatel' na konstantu celoe; i kak celoe;
p kak ukazatel' na celoe; i cp kak konstanta ukazatel' na celoe.
Posle inicializacii znacheniya ci, cpc i cp ne mogut byt' izmeneny.
Znachenie pc mozhno izmenyat' tak zhe, kak i znachenie ob容kta, na kotoryj
ukazyvaet cp. Privedem primery dopustimyh operacij:
i = ci;
*cp = ci;
pc++;
pc = cpc;
pc = p;
Nedopustimy sleduyushchie operacii:
ci = 1; // oshibka
ci++; // oshibka
*pc = 2; // oshibka
cp = &ci; // oshibka
cpc++; // oshibka
p = pc; // oshibka
Kazhdaya iz etih operacij nedopustima ili potomu, chto ona izmenyaet znachenie
ob容kta, opisannogo so specifikaciej const, ili potomu, chto delaet
takoe izmenenie vozmozhnym pozdnee s pomoshch'yu ukazatelya, nastroennogo
na ob容kt bez specifikacii const.
Analogichna situaciya so specifikaciej volatile.
Obratites' k $$R.5.17 i $$R.8.4.
Nel'zya opisyvat' ukazateli na ssylki ($$R.8.2.2) ili ukazateli
na bitovye polya ($$R.9.6).
V opisanii T D, v kotorom D imeet vid
& spisok-specifikacij-cv opt D1
tip opisyvaemogo identifikatora est'
"...spisok-specifikacij-cv ssylka na T". Tip void& nedopustim.
Naprimer, vo fragmente
void f(double& a) { a += 3.14; }
// ...
double d = 0;
f(d);
a opisyvaetsya kak parametr, yavlyayushchijsya ssylkoj, poetomu vyzov
f(d) privedet k uvelicheniyu d na 3.14. Vo fragmente
int v[20];
// ...
int& g(int i) { return v[i]; }
// ...
g(3) = 7;
opisyvaetsya: funkciya g() vozvrashchaet ssylku na celoe; poetomu
operator g() = 7; prisvoit 7 chetvertomu elementu massiva v.
Rassmotrim sleduyushchij programmnyj fragment:
struct link {
link* next;
};
link* first;
void h(link*& p) // `p' ssylka na ukazatel'
{
p->next = first;
first = p;
p = 0;
}
void k()
{
link* q = new link;
h(q);
}
Zdes' p opisano kak ssylka na ukazatel' na link, poetomu vyzov h(q)
ne izmenit znachenie q, ravnoe 0, sm. takzhe $$R.8.4.3.
Nedopustimy ssylki na ssylki, ssylki na bitovye polya ($$R.9.6),
massivy ssylok i ukazateli na ssylki. Opisanie ssylki dolzhno soderzhat'
inicializator ($$R.8.4.3), za isklyucheniem teh sluchaev, kogda opisanie
soderzhit yavnuyu specifikaciyu extern ($$R.7.1.1), ili yavlyaetsya opisaniem
chlena klassa ($$R.9.2) pri opisanii samogo klassa, ili yavlyaetsya
opisaniem parametra ili vozvrashchaemogo tipa ($$R.8.2.5),
sm. takzhe $$R.3.1.
R.8.2.3 Ukazateli na chleny
V opisanii T D, v kotorom D imeet vid
polnoe-imya-klassa :: * spisok-specifikacij-cv opt D1
tip opisyvaemogo identifikatora est'
"... spisok-specifikacij-cv ukazatel' na chlen klassa polnoe-imya-klassa tipa T".
Naprimer, vo fragmente
class X {
public:
void f(int);
int a;
};
int X::* pmi = &X::a;
void (X::* pmf)(int) = &X::f;
pmi i pmf opisyvayutsya kak ukazatel' na chlen X tipa T i ukazatel' na
chlen X tipa void(int) sootvetstvenno. |ti ob容kty mozhno ispol'zovat'
tak:
X obj;
// ...
obj.*pmi = 7; // prisvoit' 7 chlenu obj tipa int
(obj.*pmf)(7); // vyzvat' funkciyu-chlen obj
// s parametrom 7
Otmetim, chto ukazatel' na chlen nel'zya nastroit' na staticheskij
chlen klassa ($$R.9.4), sm. takzhe $$R.5.5 i $$R.5.3.
V opisanii T D, v kotorom D imeet vid
D1 [ vyrazhenie-konstanta opt ]
opisyvaetsya identifikator tipa " ... massiv T". Esli
vyrazhenie-konstanta prisutstvuet ($$R.5.19), to ono dolzhno imet'
celochislennyj tip i znachenie, bol'shee 0. |to vyrazhenie zadaet chislo
elementov massiva. Esli znachenie vyrazheniya-konstanty est' N, to
massiv imeet N elementov s indeksami ot 0 do N-1.
Massiv mozhno obrazovyvat' iz: odnogo iz osnovnyh tipov (za isklyucheniem
void), ukazatelya, ukazatelya na chleny, klassa, perechisleniya ili iz
drugogo massiva.
Esli podryad idut neskol'ko specifikacij "massiv ...", obrazuetsya
mnogomernyj massiv, prichem vyrazhenie-konstanta, zadayushchee granicy
massiva, mozhet otsutstvovat' tol'ko dlya pervogo massiva. Takoe umolchanie
polezno v sluchae parametrov funkcii tipa massiv, a takzhe kogda massiv
yavlyaetsya vneshnim, a ego opredelenie, s kotorym svyazano rezervirovanie
pamyati, nahoditsya v drugom meste. Pervoe vyrazhenie-konstanta mozhet
byt' propushcheno i v tom sluchae, esli za opisatelem sleduet
spisok-inicializatorov ($$R.8.4). Togda razmer massiva opredelyaetsya
chislom elementov, privedennyh v inicializatore ($$R.8.4.1).
V opisanii
float fa[17], *afp[17];
opisany massiv chisel tipa float i massiv ukazatelej na chisla tipa float,
a v opisanii
static int x3d[3][5][7];
opisan staticheskij trehmernyj massiv celyh razmera 3x5x7. Strogo
govorya, x3d yavlyaetsya massivom iz treh elementov, kazhdyj iz kotoryh
est' massiv iz pyati massivov, a kazhdyj iz poslednih yavlyaetsya massivom
iz semi celyh. V vyrazhenii dopustimo poyavlenie lyubogo iz sleduyushchih
vyrazhenij: x3d, x3d[i], x3d[i][j], x3d[i][j][k].
Esli v vyrazhenii uchastvuet identifikator tipa massiv, to, isklyuchaya
sluchai operanda v operaciyah sizeof ili & i inicializatora dlya
ssylki ($$R.8.4.3), ego tip preobrazuetsya v ukazatel' na pervyj
element massiva. Nesmotrya na eto preobrazovanie, massivy ne yavlyayutsya
izmenyaemymi adresami. Esli ne schitat' sluchaj ispol'zovaniya massiva
pri opisanii klassa ($$R.13.4.5), operaciya indeksacii opredelyaetsya
tak, chto E1[E2] sovpadaet s *((E1) + (E2)). S uchetom pravil
preobrazovaniya tipov dlya operacii +, esli E1 est' massiv, a E2
celoe, to E1[E2] ukazyvaet na E2-element iz E1. Poetomu, nesmotrya
na svoj asimetrichnyj vid, indeksaciya - kommutativnaya operaciya.
Analogichnoe pravilo dejstvuet i dlya mnogomernyh massivov. Esli
E - n-mernyj massiv razmera ixjx...xk, to v vyrazhenii on
preobrazuetsya v ukazatel' na (n-1)-mernyj massiv razmera jx...xk.
Esli k etomu ukazatelyu yavno ili neyavno v rezul'tate indeksacii primenyaetsya
operaciya *, ukazuemyj (n-1)-mernyj massiv sam nemedlenno preobrazuetsya
v ukazatel'.
Naprimer, rassmotrim opisanie
int x[3][5];
Zdes' opisan massiv iz 3x5 celyh. Esli v vyrazhenii poyavlyaetsya x, to
ono preobrazuetsya v ukazatel' na pervyj massiv iz pyati celyh.
Esli v vyrazhenii poyavlyaetsya x[i], chto ekvivalentno *(x+i), v nachale
x preobrazuetsya v ukazatel', kak bylo skazano vyshe, zatem x+i
preobrazuetsya k tipu x, dlya chego neobhodimo i umnozhit' na razmer ob容kta,
na kotoryj ukazyvaet x, t.e. na razmer pyati celyh. Zatem proishodit
slozhenie i primenyaetsya kosvennost', posle chego poluchim massiv (iz pyati
celyh), kotoryj v svoyu ochered' preobrazuetsya v ukazatel' na pervoe iz
celyh. Esli est' eshche odna indeksaciya, process povtoryaetsya, i na etot raz
my poluchim v rezul'tate celoe.
Iz vsego etogo sleduet, chto massivy V S++ hranyatsya po strokam
(poslednij indeks izmenyaetsya bystree vsego), a znachenie pervogo
indeksa iz opisaniya pozvolyaet vychislit' razmer pamyati, neobhodimoj
dlya massiva, odnako pri vychislenii indeksnogo vyrazheniya pervyj indeks
roli ne igraet.
V opisanii T D, v kotorom D imeet vid
D1 (spisok-opisanij-parametrov ) spisok-specifikacij-cv opt
opisyvaemyj identifikator imeet tip
"...spisok-specifikacij-cv funkciya s parametrami tipa
spisok-opisanij-parametrov vozvrashchayushchaya T".
spisok-opisanij-parametrov:
spisok-opisanij-param opt ... opt
spisok-opisanij-param , ...
spisok-opisanij-param:
opisanie-parametra
spisok-opisanij-param , opisanie-parametra
opisanie-parametra:
specifikacii-opisaniya opisatel'
specifikacii-opisaniya opisatel' = vyrazhenie
specifikacii-opisaniya abstraktnyj-opisatel' opt
specifikacii-opisaniya abstraktnyj-opisatel' opt = vyrazhenie
Esli spisok-opisanij-parametrov zavershaetsya ellipsisom (...),
pro chislo parametrov izvestno tol'ko to, chto ono bol'she ili ravno
chisla zadannyh parametrov, esli spisok parametrov pust, to funkciya
parametrov ne imeet. Spisok parametrov void ekvivalenten pustomu
spisku parametrov. Ne schitaya etogo sluchaya, void ne mozhet byt' tipom
parametra (hotya tipy, poluchaemye iz void, takie kak void*, dopustimy).
R.8.3 Opredeleniya funkcij
Opredeleniya funkcij imeyut vid
opredelenie-funkcii:
specifikacii-opisaniya opt opisatel' inicializator-ctor telo-funkcii
telo-funkcii:
sostavnoj-operator
Konstrukciya opisatel' iz opredeleniya-funkcii dolzhna soderzhat' opisatel'
vida
D1 ( spisok-opisanij-parametrov ) spisok-specifikacij-cv opt
v sootvetstvii s opredeleniyami iz $$R.8.2.5
Formal'nye parametry otnosyatsya k oblasti vidimosti samogo
bol'shogo bloka tela-funkcii.
Privedem primer polnogo opredeleniya funkcii.
int max( int a, int b, int c)
{
int m = (a > b) ? a : b;
return (m > c) ? m : c;
}
Zdes' int predstavlyaet specifikacii-opisaniya, max(int a, int b, int c)
- opisatel', a { /* ... */ } - telo-funkcii.
Konstrukciya inicializator-ctor ispol'zuetsya tol'ko v konstruktorah,
sm. $$R.9.3.1 i $$R.12.6.
Konstrukciya spisok-specifikacij-cv mozhet uchastvovat':
v opisanii nestaticheskoj funkcii-chlena, v opredelenii nestaticheskoj
funkcii-chlena ili v opisanii ukazatelya na funkciyu-chlen, sm. $$R.9.3.1.
Ona otnositsya k tipu funkcii.
Otmetim, chto neispol'zuemym formal'nym parametram imena mozhno
ne davat', naprimer,
void print(int a, int)
{
printf("a = %d\n",a);
}
Za opisatelem mozhet idti nachal'noe znachenie opisyvaemogo identifikatora.
inicializator:
= vyrazhenie-prisvaivaniya
= { spisok-inicializatorov , opt }
( spisok-vyrazhenij )
spisok-inicializatorov:
vyrazhenie-prisvaivaniya
spisok-inicializatorov , vyrazhenie-prisvaivaniya
{ spisok-inicializatorov , opt }
Avtomaticheskie, registrovye, staticheskie i vneshnie peremennye
mozhno inicializirovat' proizvol'nymi vyrazheniyami, soderzhashchimi
konstanty i opisannye ranee peremennye i funkcii.
int f(int);
int a = 2;
int b = f(a);
int c(b);
Ukazatel' tipa const T*, t.e. ukazatel' na konstantu T, mozhet
inicializirovat'sya ukazatelem tipa T*, no inicializaciya dlya ukazatelej
v obratnom poryadke nezakonna. Ob容kty tipa T mozhno inicializirovat'
ob容ktami tipa T nezavisimo ot ispol'zovaniya specifikacij const ili
volatile v tipah inicializiruemoj peremennoj ili inicializatora,
naprimer,
int a;
const int b = a;
int c = b;
const int* p0 = &a;
const int* p1 = &b;
int* p2 = &b; // oshibka: ukazatel' bez const
// nastraivaetsya na ob容kt const
int *const p3 = p2;
int *const p4 = p1; // oshibka: ukazatel' bez const
// nastraivaetsya na ob容kt const
const int* p5 = p1;
Zdes' prichina obeih oshibok odna: esli dopustit' podobnuyu inicializaciyu,
ona pozvolit izmenyat' s pomoshch'yu ukazatelya bez sootvetstvuyushchej
specifikacii znachenie chego-to, chto bylo opisano kak const.
Na vyrazheniya dlya standartnyh znachenij parametrov nakladyvaetsya
bol'she ogranichenij, sm. $$R.8.2.6.
Inicializaciya ob容ktov klassov s pomoshch'yu konstruktorov opisyvaetsya
v $$R.12.6.1. Kopirovanie ob容ktov klassov opisyvaetsya v $$R.12.8.
Poryadok inicializacii staticheskih ob容ktov opredelyaetsya v $$R.3.4
i $$R.6.7.
Garantiruetsya, chto peremennye staticheskogo klassa pamyati ($$R.3.5),
kotorye ne byli inicializirovany, v kachestve nachal'nogo znacheniya
poluchat 0, privedennyj k nuzhnomu tipu. To zhe spravedlivo dlya staticheskih
chlenov ob容ktov klassa. Nachal'nye znacheniya avtomaticheskih i
registrovyh peremennyh, kotorye ne byli inicializirovany, neopredeleny.
Esli inicializator otnositsya k ukazatelyu ili ob容ktu arifmeticheskogo
tipa, on sostoit iz odnogo vyrazheniya (vozmozhno v skobkah). V kachestve
nachal'nogo znacheniya ob容kta beretsya znachenie vyrazheniya, proishodyat
takie zhe preobrazovaniya tipa, kak i v sluchae prisvaivaniya.
Zametim, chto poskol'ku () ne yavlyaetsya inicializatorom,
opisanie
X a();
zadaet ne ob容kt a tipa klass X, a yavlyaetsya opisaniem funkcii bez
parametrov, vozvrashchayushchej X.
Inicializator dlya staticheskogo chlena prinadlezhit oblasti
vidimosti chlena klassa, naprimer,
int a;
struct X {
static int a;
static int b;
};
int X::a = 1;
int X::b = a; // X::b = X::a
Agregatom nazyvaetsya massiv ili ob容kt tipa klass ($$R.9), ne imeyushchij
konstruktorov ($$R.12.1), chastnyh ili zashchishchennyh chlenov ($$R.11),
bazovyh klassov ($$R.10) i virtual'nyh funkcij ($$R.10.2). Esli
agregat inicializiruetsya, to inicializatorom dolzhen byt'
spisok-inicializatorov, kotoryj sostoit iz zaklyuchennogo v figurnye
skobki spiska, razdelennogo zapyatymi, inicializatorov dlya chlenov
agregata. Inicializatory idut v vozrastayushchem poryadke indeksov ili
chlenov agregata. Esli agregat soderzhit vlozhennye agregaty, eto
pravilo primenyaetsya rekursivno dlya chlenov vlozhennyh agregatov. Esli
inicializatorov v spiske men'she, chem chlenov agregata, to on
dopolnyaetsya nulevymi znacheniyami sootvetstvuyushchih tipov.
Naprimer, v sleduyushchem fragmente
struct S { int a; char* b; int c; }
S ss = { 1, "asdf" };
ss.a inicializiruetsya znacheniem 1, ss.b - "asdf", a ss.c - 0.
Krome togo, agregat, yavlyayushchijsya klassom, mozhno inicializirovat'
ob容ktom etogo klassa ili klassa, yavlyayushchegosya obshchim proizvodnym
ot nego ($$R.12.8).
Figurnye skobki razbirayutsya sleduyushchim obrazom. Esli
spisok-inicializatorov nachinaetsya levoj figurnoj skobkoj, to
spisok inicializatorov, razdelennyh zapyatymi, zadaet
znacheniya chlenam agregata, prichem schitaetsya oshibkoj, esli
inicializatorov bol'she, chem chlenov. Inache, esli spisok-inicializatorov
ili vlozhennyj agregat ne nachinaetsya levoj figurnoj skobkoj, to
iz spiska ispol'zuetsya takoe chislo elementov, kotoroe nuzhno dlya
inicializacii chlenov tekushchego agregata; vse ostavshiesya elementy
ispol'zuyutsya dlya inicializacii chlenov sleduyushchego agregata, v kotoryj
vlozhen tekushchij agregat.
Naprimer, v opredelenii
int x[] = { 1, 3, 5 };
massiv x inicializiruetsya kak odnomernyj massiv iz treh elementov,
poskol'ku razmer massiva ne ukazan, i privedeno tri inicializatora.
Privedem primer inicializacii s polnoj skobochnoj strukturoj.
float y[4][3] = {
{ 1, 3, 5 },
{ 2, 4, 6 },
{ 3, 5, 7},
};
Zdes' znacheniya 1, 3, 5 inicializiruyut pervuyu stroku massiva y[0],
t.e. y[0][0], y[0][1] i y[0][2]. Analogichno, sleduyushchie dve stroki
inicializiruyut y[1] i y[2]. Inicializatory privedeny ne polnost'yu,
poetomu y[3] inicializiruetsya nulyami. Tochno takogo zhe rezul'tata
mozhno dostich' s pomoshch'yu takoj inicializacii:
float y[4][3] = {
1, 3, 5, 2, 4, 6, 3, 5, 7,
};
Poslednij (samyj pravyj) indeks izmenyaetsya bystree vsego.
V poslednem primere inicializator dlya y nachinaetsya levoj figurnoj
skobkoj, no dlya y[0] skobki ne zadano, poetomu iz spiska ispol'zuetsya
tri elementa, takzhe po tri posledovatel'nyh elementa ispol'zuetsya dlya
y[1] i y[2]. V sleduyushchem primere
float y[4][3] = {
{ 1 }, { 2 }, { 3 }, { 4 }
};
inicializiruetsya pervyj stolbec y (kotoryj rassmatrivaetsya kak
dvumernyj massiv), a ostal'nye stolbcy prinimayut znachenie 0.
Inicializaciya massiva ob容ktov tipa klass s pomoshch'yu konstruktorov
opisyvaetsya v $$R.12.6.1.
Inicializator dlya ob容dineniya bez konstruktora dolzhen byt'
ili otdel'nym vyrazheniem tipa ob容dineniya, ili zaklyuchennym v figurnye
skobki, inicializatorom pervogo chlena ob容dineniya, naprimer,
union u { int a; char* b; };
u a = { 1 };
u b = a;
u c = 1; // oshibka
u d = { 0, "asdf" }; // oshibka
u e = { "asdf" }; // oshibka
CHislo inicializatorov ne dolzhno prevyshat' chisla chlenov ili
elementov, kotorye inicializiruyutsya. Naprimer, sleduyushchaya
inicializaciya oshibochna:
char cv[4] = { 'a', 's', 'd', 'f', 0 }; // oshibka
R.8.4.2 Simvol'nye massivy
Massiv simvolov (nevazhno, znakovyh ili bezznakovyh) mozhno
inicializirovat' strokoj-literalom: simvoly stroki posledovatel'no
inicializiruyut elementy massiva. Sleduyushchee opredelenie daet primer
simvol'nogo massiva, elementy kotorogo inicializiruyutsya strokoj:
char msg[] = "Syntax error on line %s\n";
Zametim, chto poskol'ku '\n' zadaet odin simvol, i poskol'ku dobavlyaetsya
zavershayushchij simvol '\0', sizeof(msg) ravno 25.
Nel'zya zadavat' bol'she inicializatorov, chem est' elementov v massive,
poetomu sleduyushchij primer oshibochen: zdes' net mesta dlya podrazumevayushchegosya
simvola konca stroki ('\0'):
char cv[4] = "asdf"; // oshibka
Peremennaya, opisannaya kak T&, t.e. "ssylka na tip T" ($$R.8.2.2),
dolzhna inicializirovat'sya ob容ktom tipa T ili ob容ktom, kotoryj
mozhno preobrazovat' k tipu T, naprimer,
void f()
{
int i;
int& r = i; // `r' ssylaetsya na `i'
r = 1; // `i' prinimaet znachenie 1
int* p = &r; // `p' ukazyvaet na `i'
int& rr = r; // `rr' ssylaetsya na to, na chto ssylalos' `r',
// t.e. na `i'
};
Ssylku posle inicializacii nel'zya izmenyat' tak, chtoby ona
oboznachala drugoj ob容kt. Otmetim, chto inicializaciya ssylki
traktuetsya sovsem ne tak, kak prisvaivanie ssylke. Peredacha
parametra ($$R.5.2.2) i operaciya vozvrata znacheniya funkcii ($$R.6.6.3)
schitayutsya inicializaciej.
Inicializator dlya ssylki mozhno opuskat' tol'ko v opisanii
parametra ($$R.8.2.5), v opisanii vozvrashchaemogo funkciej tipa,
v opisanii chlena klassa pri opisanii samogo klassa ($$R.9.2) i tam,
gde yavno ispol'zovana specifikaciya extern, naprimer,
int& r1; // oshibka: net inicializacii
extern int& r2; // normal'no
Esli inicializator dlya ssylki na tip T yavlyaetsya adresom tipa T
ili tipom, proizvodnym ot T ($$R.10), dlya kotorogo T sluzhit
dostupnym bazovym tipom ($$R.4.6), ssylka budet oboznachat' znachenie,
zadannoe inicializatorom. Inache, v tom i tol'ko tom sluchae, kogda
ssylka oboznachaet ob容kt so specifikaciej const, budet sozdan ob容kt
tipa T i proinicializirovan znacheniem, zadannym inicializatorom.
Teper' ssylka igraet rol' imeni etogo ob容kta, naprimer,
double d = 1.0;
double& rd = d; // rd ssylaetsya na `d'
const double& rcd = d; // rcd ssylaetsya na `d'
double& rd2 = 1; // oshibka: nesootvetstvie tipa
const double& rcd2 = 1;// rcd2 ssylaetsya na vremennyj ob容kt
// so znacheniem `1'
Ssylku na volatile T mozhno inicializirovat' ob容ktom tipa
volatile T ili prosto T, no ne const T. Ssylku na const T mozhno
inicializirovat' const T, prosto T ili chem-to, chto mozhno preobrazovat'
v tip T, no ne volatile T. Ssylku na tip T (bez const ili volatile)
mozhno inicializirovat' tol'ko ob容ktom tipa T.
Vremya zhizni vremennogo ob容kta, sozdannogo pri opisannoj
inicializacii, opredelyaetsya tekushchej oblast'yu vidimosti, v kotoroj
on byl sozdan ($$R.3.5). Otmetim, chto ssylku na klass B mozhno
inicializirovat' ob容ktom klassa D pri uslovii, chto V yavlyaetsya
odnoznachno opredelennym i dostupnym bazovym klassom dlya D (togda
govoryat, chto "D est' B"), sm. $$R.4.7.
Klass est' tip. Ego imya ispol'zuetsya kak imya-klassa ($$R.9.1), t.e.
stanovitsya zarezervirovannym slovom v ego oblasti vidimosti.
imya-klassa:
identifikator
Dlya obrazovaniya konstrukcii imya-klassa ispol'zuyutsya specifikacii-klassa
i specifikacii-slozhnogo-tipa ($$R.7.1.6). Ob容kt klassa sostoit iz
posledovatel'nosti (vozmozhno pustoj) chlenov.
specifikaciya-klassa:
zagolovok-klassa { spisok-chlenov opt }
zagolovok-klassa:
sluzhebnoe-slovo-klassa identifikator opt spec-bazovyh opt
sluzhebnoe-slovo-klassa imya-klassa spec-bazovyh opt
sluzhebnoe-slovo-klassa:
class
struct
union
Imya klassa mozhno ispol'zovat' v kachestve konstrukcii imya-klassa
dazhe v spiske-chlenov samogo etogo klassa. Obychno specifikaciyu-klassa
nazyvayut opisaniem klassa. Klass schitaetsya opredelennym, kak tol'ko
poyavitsya specifikaciya-klassa, nesmotrya na to, chto ego funkcii-chleny
mogut byt' eshche neopredeleny.
Ob容kty pustogo klassa imeyut nenulevoj razmer.
Ob容kty tipa klass mozhno prisvaivat', peredavat' v kachestve
parametrov funkcij i poluchat' v kachestve znacheniya, vozvrashchaemogo
funkciej (za isklyucheniem ob容ktov teh klassov, dlya kotoryh kopirovanie
ogranicheno, sm. $$R.12.8). Drugie vozmozhnye operacii, takie, kak
sravnenie na ravenstvo, mogut opredelyat'sya pol'zovatelem, sm. $$R.13.4.
Strukturoj nazyvaetsya klass, opisannyj so sluzhebnym-slovom-klassa
struct; ee chleny i bazovye klassy ($$R.10) schitayutsya obshchimi po
opredeleniyu ($$R.11). Ob容dineniem nazyvaetsya klass, opisannyj so
sluzhebnym-slovom-klassa union; ego chleny schitayutsya obshchimi po
opredeleniyu, i v lyuboj moment vremeni ob容dinenie soderzhit tol'ko
odin chlen ($$R.9.5).
Opisanie klassa porozhdaet novyj tip. Naprimer, nizhe opisyvayutsya
tri peremennye treh razlichnyh tipov:
struct X { int a; };
struct Y { int a; };
X a1;
Y a2;
int a3;
Otsyuda sleduet, chto takie prisvaivaniya privodyat k nesootvetstviyu
tipov:
a1 = a2; // oshibka: Y prisvaivaetsya X
a1 = a3; // oshibka: int prisvaivaetsya X
Nizhe opisyvaetsya peregruzka ($$R.13) funkcii f(), a ne prosto
povtornoe opisanie toj zhe funkcii:
int f(X);
int f(Y);
Po toj zhe prichine nel'zya dvazhdy opredelyat' klass, eto vidno iz
primera nizhe, gde dvazhdy opredelen S:
struct S { int a; };
struct S { int a; }; // oshibka, povtornoe opredelenie
Opisanie klassa vklyuchaet imya klassa v tu oblast' vidimosti, vnutri
kotoroj ono proizoshlo, i zakryvaet lyuboj klass, ob容kt, funkciyu ili
drugoe opisanie etogo imeni v ob容mlyushchej oblasti vidimosti ($$R.3.2).
Esli imya klassa opisano v takoj oblasti vidimosti, gde uzhe byl
opisan ob容kt s takim zhe imenem, funkciya ili element perechisleniya, to
obrashchat'sya k klassu mozhno tol'ko s pomoshch'yu konstrukcii
specifikaciya-slozhnogo-tipa ($$R.7.1.6), naprimer:
struct stat {
// ...
};
stat gstt; // prosto `stat' ispol'zuetsya dlya
// opredeleniya peremennoj
int stat(struct stat*); // pereopredelenie `stat' kak funkcii
void f()
{
struct stat* ps; // nuzhen prefiks struct
// dlya zadaniya struktury stat
// ...
stat(ps); // vyzov stat()
// ...
}
Konstrukciya specifikaciya-slozhnogo-tipa vmeste so
sluzhebnym-slovom-klassa, no bez opisaniya ob容kta ili funkcii takzhe
mozhet sluzhit' dlya zadaniya imeni klassa, kak i opisanie klassa, odnako
v etom sluchae klass ne schitaetsya opredelennym, naprimer:
struct s { int a; };
void g()
{
struct s; // skryvaet global'nuyu strukturu `s'
s* p; // ispol'zuetsya lokal'naya struktura `s'
struct s { char* p; }; // opisanie lokal'noj struktury `s'
}
Takie pravila pozvolyayut klassam ssylat'sya drug na druga pri ih
opisanii, primer,
class vector;
class matrix {
// ...
friend vector operator*(matrix&, vector&);
};
class vector {
// ...
friend vector operator*(matrix&, vector&);
};
Opisanie friend (druzhestvennye funkcii) obsuzhdaetsya v $$R.11.4, a
funkciya operator v $$R.13.4. Esli klass, ukazannyj kak drug, poka
eshche ne opisan, ego imya schitaetsya prinadlezhashchim toj zhe oblasti
vidimosti, v kotoroj nahoditsya imya klassa, soderzhashchego opisanie
friend ($$R.11.4).
V opisanii ob容ktov ili funkcij mozhno takzhe ispol'zovat'
konstrukciyu specifikaciya-slozhnogo-tipa ($$R.7.1.6). Ee ispol'zovanie
otlichaetsya ot opisaniya klassa tem, chto esli klass, ch'e imya ukazano
v specifikacii, nahoditsya v tekushchej oblasti vidimosti, to imya iz
etoj specifikacii budet ssylat'sya na nego, naprimer:
struct s { int a; }
void g()
{
struct* s p = new s; // obrashchenie k global'noj `s'
p->a = 1;
}
Imya schitaetsya opisannym srazu zhe posle poyavleniya ego identifikatora
v opisanii. Otsyuda sleduet, chto v opisanii
class A * A;
A v nachale zadaetsya, kak imya klassa, a zatem ono pereopredelyaetsya
kak imya ukazatelya na ob容kt etogo klassa, poetomu dlya oboznacheniya etogo
klassa sleduet ispol'zovat' specifikaciyu-slozhnogo tipa class A. Takoe
"tryukachestvo" s imenami mozhet vyzvat' nedoumenie, i luchshe ego izbegat'.
Konstrukciya imya-typedef ($$R.7.1.3) oboznachaet klass i schitaetsya
imenem-klassa, sm. takzhe $$R.7.1.3.
spisok-chlenov:
opisanie-chlena spisok-chlenov opt
specifikaciya-dostupa : spisok-chlenov opt
opisanie-chlena:
specifikacii-opisaniya opt spisok-opisatelej-chlenov opt ;
opredelenie-funkcii ; opt
utochnennoe-imya ;
spisok-opisatelej-chlenov:
opisatel'-chlena
spisok-opisatelej-chlenov , opisatel'-chlena
opisatel'-chlena:
opisatel' specifikaciya-chistoj opt
identifikator opt : vyrazhenie-konstanta
specifikaciya-chistoj:
= 0
S pomoshch'yu konstrukcii spisok-chlenov mozhno opisat' dannye, funkcii,
klassy, elementy perechisleniya ($$R.7.2), bitovye polya, druzej
($$R.11.4) i imena tipov ($$R.7.1.3, $$R.9.1). Krome togo,
spisok-chlenov mozhet soderzhat' opisaniya, ustanavlivayushchie dostup k
imenam chlenov, sm. $$R.11.3. Nikakoj chlen ne mozhet byt' dvazhdy
opisan v spiske-chlenov. Spisok-chlenov opredelyaet vse mnozhestvo
chlenov dannogo klassa, t.e. nel'zya dobavit' eshche odin chlen v kakom-libo
drugom opisanii.
Otmetim, chto odno imya mozhet oboznachat' neskol'ko funkcij-chlenov
pri uslovii, chto ih tipy dostatochno otlichayutsya drug ot druga ($$R.13).
Ukazhem, chto opisatel'-chlena ne mozhet soderzhat' inicializatora ($$R.8.4).
Inicializaciya chlena vozmozhna s pomoshch'yu konstruktora, sm. $$R.12.1.
CHlen ne mozhet imet' specifikaciyu auto, extern ili register.
Konstrukciya specifikacii-opisaniya mozhet otsutstvovat' tol'ko v
opisanii funkcii. Konstrukciya spisok-opisatelej-chlenov mozhet
opuskat'sya tol'ko posle konstrukcij specifikaciya-klassa,
specifikaciya-perechisleniya ili specifikaciya-opisaniya, esli poslednyaya
imeet vid friend specifikaciya-slozhnogo-tipa. Konstrukciya
specifikaciya-chistoj ispol'zuetsya tol'ko pri opisanii virtual'noj
funkcii ($$R.10.2).
Esli chleny yavlyayutsya ob容ktami klassov, to eti klassy dolzhny
byt' ranee opisany. V chastnosti, klass C1 ne mozhet soderzhat' ob容kt
klassa C1, no mozhet soderzhat' ukazatel' ili ssylku na klass C1.
Esli v tipe nestaticheskogo chlena ispol'zuetsya massiv, to vse
razmery vseh indeksov massiva dolzhny byt' ukazany.
Privedem prostoj primer opisaniya klassa:
struct tnode {
char tword[20];
int count;
tnode *left;
tnode *right;
};
Zdes' klass soderzhit massiv iz dvadcati simvolov, celoe i dva
ukazatelya na tu zhe strukturu. Posle poyavleniya takogo opisaniya
sleduyushchee:
tnode s, *sp;
zadaet s kak ob容kt tipa tnode i sp kak ukazatel' na tnode. S uchetom
etih opisanij s->count oboznachaet chlen count struktury, na kotoruyu
ukazyvaet sp; s.left oboznachaet ukazatel' left na podderevo
struktury s; s.right->tword[0] oboznachaet pervyj simvol chlena
tword poddereva struktury s, na kotoruyu ukazyvaet right.
Nestaticheskie chleny klassa, predstavlyayushchie dannye i opisannye
podryad i bez ispol'zovaniya specifikacii-dostupa, razmeshchayutsya vnutri
ob容kta tipa klass tak, chto pozzhe opisannye chleny imeyut bol'shie adresa.
Poryadok razmeshcheniya takih chlenov, esli ih opisanie peremezhaetsya
opisaniyami so specifikaciej-dostupa, zavisit ot realizacii ($$R.11.1).
Prinyatye v realizacii pravila vyravnivaniya mogut privesti k tomu,
chto dva sosednih chlena ne budut raspolagat'sya srazu drug za drugom.
K etomu zhe mogut privesti pravila vydeleniya pamyati dlya virtual'nyh
funkcij ($$R.10.2) i virtual'nyh bazovyh klassov ($$R.10.1);
sm. takzhe $$R.5.4.
Funkciya-chlen ($$R.9.3), imya kotoroj sovpadaet s imenem klassa,
yavlyaetsya konstruktorom ($$R.12.1). Imya staticheskogo chlena dannyh,
elementa perechisleniya, chlena bezymyannogo ob容dineniya ili vlozhennogo
tipa ne mozhet sovpadat' s imenem klassa.
Funkciya, opisannaya kak chlen (bez specifikacii friend $$R.11.4),
nazyvaetsya funkciya-chlen i vyzyvaetsya v sootvetstvii s sintaksisom
chlena klassa ($$R.5.2.4), naprimer:
struct tnode {
char tword[20];
int count;
tnode *left;
tnode *right;
void set(char*, tnode* l, tnode *r);
};
Zdes' set yavlyaetsya funkciej-chlenom i mozhet vyzyvat'sya tak:
void f(tnode n1, tnode n2)
{
n1.set("abc",&n2,0);
n2.set("def",0,0);
}
Schitaetsya, chto opredelenie funkcii-chlena prinadlezhit oblasti
vidimosti ee klassa. |to oznachaet, chto v funkcii-chlene (esli ona
nestaticheskaya, $$R.9.4) mozhno neposredstvenno ispol'zovat' imena
chlenov ee klassa. V staticheskoj funkcii-chlene mozhno neposredstvenno
ispol'zovat' imena tol'ko staticheskih chlenov, elementov perechisleniya
i vlozhennyh tipov. Esli opredelenie funkcii-chlena nahoditsya vne
opisaniya klassa, ee imya sleduet utochnit' imenem klassa s pomoshch'yu
operacii ::, naprimer:
void tnode::set(char* w, tnode* l, tnode* r)
{
count = strlen(w)+1;
if (sizeof(tword)<=count)
error("tnode string too long");
strcpy(tword,w);
left = 1;
right = r;
}
Oboznachenie tnode::set ukazyvaet, chto funkciya set yavlyaetsya chlenom i
nahoditsya v oblasti vidimosti klassa tnode. Imena chlenov tword,
count, left i right otnosyatsya k chlenam togo ob容kta, s imenem
kotorogo vyzyvalas' Poetomu v vyzove n1.set("abc",&n2,0) tword
oboznachaet n1.tword, a v vyzove n2.set("def",0,0) tword oboznachaet
n2.tword. Funkcii strlen, error i strcpy dolzhny byt' opisany gde-to
v programme.
CHleny mozhno opredelyat' ($$R.3.1) vne opisaniya klassa; esli v
opisanii klassa oni byli opisany, no ne opredeleny, ih ne sleduet
opisyvat' zanovo, sm. $$R.3.3. Posle opredeleniya klassa
funkcii-chleny etogo klassa mozhno ispol'zovat' pri opisanii druzej.
Vsyakaya vyzyvaemaya v programme funkciya-chlen dolzhna imet' v tochnosti
odno opredelenie.
Rezul'tat vyzova nestaticheskoj funkcii-chlena ($$R.9.4) klassa X,
kogda ona vyzyvaetsya ne s ob容ktom klassa X, neopredelen.
V nestaticheskoj ($$R.9.3) funkcii-chlene sluzhebnoe slovo this oboznachaet
ukazatel' na ob容kt, s kotorym eta funkciya vyzyvalas'. V funkcii-chlene
klassa X tip this est' X *const, esli tol'ko funkciya-chlen ne opisana
so specifikaciej const ili volatile; dlya etih sluchaev this imeet
tip const X *const ili volatile X *const sootvetstvenno. Esli
funkciya opisana s ukazaniem const i volatile, to tip this budet
const volatile X *const, sm. takzhe $$R.18.3.3. Privedem primer:
struct s {
int a;
int f() const;
int g() { return a++; }
int h() const { return a++; } // oshibka
};
int s::f() const { return a; }
Operaciya a++ v tele funkcii s::h oshibochna, poskol'ku s ee pomoshch'yu
delaetsya popytka izmenit' ob容kt (chast' ego), s kotorym vyzyvalas'
funkciya s::h(). |to nedopustimo dlya funkcii-chlena, opisannoj so
specifikaciej const, t.k. this yavlyaetsya ukazatelem na const, inymi
slovami, *this imeet specifikaciyu const.
Funkciya-chlen const (t.e. funkciya-chlen, opisannaya so specifikaciej
const) mozhet vyzyvat'sya kak dlya ob容ktov const, tak i dlya ob容ktov
bez specifikacii const, togda kak funkciya-chlen bez specifikacii
const mozhet vyzyvat'sya tol'ko dlya ob容ktov bez specifikacii const,
naprimer:
void k(s& x, const s& y)
{
x.f();
x.g();
y.f();
y.g(); // oshibka
}
Zdes' vyzov y.g() yavlyaetsya oshibkoj, t.k. y est' const, a s::g() -
funkciya-chlen bez specifikacii const, kotoraya mozhet izmenyat'
(i izmenyaet) ob容kty, dlya kotoryh ona vyzyvalas'.
Analogichno, tol'ko funkciya-chlen volatile (t.e. funkciya-chlen,
opisannaya so specifikaciej volatile) mozhet vyzyvat'sya dlya ob容ktov
so specifikaciej volatile. Funkciya-chlen mozhet byt' odnovremenno
const i volatile.
Dlya ob容ktov const ili volatile mogut vyzyvat'sya konstruktory
($$R.12.1) i destruktory ($$R.12.4). Konstruktory ($$R.12.1) i
destruktory ($$R.12.4) nel'zya opisyvat' so specifikaciyami const
ili volatile.
R.9.3.2 Funkcii-chleny so specifikaciej inline
Funkciyu-chlen mozhno opredelit' ($$R.8.3) v opisanii klassa, v
takom sluchae ona schitaetsya podstanovkoj (inline, $$R.7.1.2).
Opredelyat' funkciyu v opisanii klassa - eto ekvivalentno tomu,
chtoby opisyvat' funkciyu i opredelyat' ee so specifikaciej inline
srazu zhe posle opisaniya klassa. Schitaetsya, chto takoj perenos
opredeleniya funkcii proishodit posle preprocessornoj obrabotki
do stadii sintaksicheskogo analiza i kontrolya tipov. Poetomu
programmnyj fragment
int b;
struct x {
char* f() { return b; }
char* b;
};
ekvivalenten
int b;
struct x {
char* f();
char* b;
};
inline char* x::f() { return b; } // perenos
Zdes' v funkcii x::f() ispol'zuetsya x::b, a ne global'noe b.
Funkcii-chleny mozhno opredelyat' dazhe v opisanii lokal'nyh ili
vlozhennyh klassov, gde takoj perenos budet sintaksicheski nezakonnym.
Lokal'nye klassy obsuzhdayutsya v R.9.8, a vlozhennye klassy v $$R.9.7.
R.9.4 Staticheskie chleny
Dlya chlena klassa, predstavlyayushchego dannye ili funkciyu, mozhno pri opisanii
klassa zadat' specifikaciyu static. Dlya staticheskogo chlena,
predstavlyayushchego dannye, v programme sushchestvuet tol'ko odin ekzemplyar,
kotorym vladeyut vse ob容kty etogo klassa. Staticheskij chlen ne yavlyaetsya
chast'yu ob容kta klassa. Staticheskie chleny global'nogo klassa
podlezhat vneshnemu svyazyvaniyu ($$R.3.3). Opisanie staticheskogo chlena,
predstavlyayushchego dannye, v opisanii klassa ne schitaetsya opredeleniem.
Opredelenie dolzhno byt' dano v drugom meste, sm. takzhe. $$R.18.3.
Staticheskaya funkciya-chlen ne imeet ukazatel' this, poetomu dlya
dostupa k nestaticheskim chlenam svoego klassa ona dolzhna ispol'zovat'
operacii . ili ->. Staticheskaya funkciya-chlen ne mozhet byt' virtual'noj.
Nedopustimy staticheskie i nestaticheskie funkcii-chleny s odnim imenem
i odinakovymi tipami parametrov.
Staticheskie chleny lokal'nogo klassa ($$R.9.8) ne podlezhat
svyazyvaniyu i ne mogut opredelyat'sya vne opisaniya klassa. Otsyuda
sleduet, chto lokal'nye klassy ne mogut imet' staticheskih chlenov,
predstavlyayushchih dannye.
K staticheskomu chlenu mem klassa c1 mozhno obrashchat'sya kak c1::mem
($$R.5.1), t.e. nezavisimo ni ot kakogo ob容kta. K nemu takzhe mozhno
obrashchat'sya s pomoshch'yu operacij dostupa k chlenam . i ->. Esli k
staticheskomu chlenu proishodit obrashchenie s pomoshch'yu operacij dostupa,
vyrazheniya, stoyashchie sleva ot . ili -> ne ekvivalentny. Staticheskij
chlen mem sushchestvuet dazhe, esli ne sozdano ni odnogo ob容kta klassa
c1. V primere nizhe run_chain, idle i drugie chleny sushchestvuyut dazhe,
esli ne bylo sozdano ni odnogo ob容kta klassa process:
class process {
static int no_of_process;
static process* run_chain;
static process* running;
static process* idle;
// ...
public:
// ...
int state();
static void reshedule();
// ...
};
Zdes' k funkcii reshedule mozhno obratit'sya bez ukazaniya ob容kta
klassa process takim obrazom:
void f()
{
process::reshedule();
}
Staticheskie chleny global'nyh klassov inicializiruyutsya tochno tak zhe
kak global'nye ob容kty, no oblast' ih vidimosti - fajl, naprimer:
void process::reshedule() { /* ... */ };
int process::no_of_process = 1;
process* process::running = get_main();
process* process::run_chain = process::running;
Staticheskie chleny podchinyayutsya obychnym pravilam dostupa k chlenam
klassa ($$R.11), za isklyucheniem togo, chto ih mozhno inicializirovat'
v fajlovoj oblasti vidimosti.
V tipe staticheskogo chlena ne uchastvuet imya klassa, tak tip
process::no_of_process est' int, a tip &process::reshedule() -
void(*)().
Ob容dinenie mozhno predstavit' kak strukturu, vse chleny imeyut
nulevoe smeshcheniya, a razmer ee dostatochno velik, chtoby
vmeshchat' lyuboj iz ee chlenov. V lyuboj moment vremeni ob容dinenie
mozhet soderzhat' tol'ko odin chlen. V ob容dinenii mogut byt'
funkcii-chleny (v tom chisle konstruktory i destruktory), no ne
virtual'nye funkcii ($$R.10.2). Ob容dinenie ne mozhet imet' bazovyh
klassov i ne mozhet samo ispol'zovat'sya v kachestve bazovogo klassa.
CHlenom ob容dineniya ne mozhet byt' ob容kt klassa s konstruktorom ili
destruktorom, a takzhe s opredelennoj pol'zovatelem operaciej
prisvaivaniya ($$R.13.4.3). Ob容dinenie ne mozhet soderzhat' staticheskih
chlenov, predstavlyayushchih dannye.
Ob容dinenie vida
union { spisok-chlenov }
nazyvaetsya bezymyannym ob容dineniem, ono opredelyaet ob容kt bez imeni
(i bez tipa). Imena vseh chlenov bezymyannogo ob容dineniya dolzhny
otlichat'sya ot drugih imen v toj oblasti vidimosti, v kotoroj opisano
ob容dinenie; ih mozhno ispol'zovat' v etoj oblasti vidimosti
neposredstvenno, bez obychnyh operacij dostupa k chlenam ($$R.5.2.4).
Privedem primer:
void f()
{
union { int a; char* p; };
a = 1;
// ...
p = "Jennifer";
// ...
}
Zdes' a i p ispol'zuyutsya kak obychnye peremennye (ne chleny), no poskol'ku
oni vhodyat v odno ob容dinenie, ih adresa sovpadayut.
Global'nye bezymyannye ob容dineniya mozhno opisat' so specifikaciej
static. Bezymyannye ob容dineniya ne dolzhny soderzhat' chastnyh ili
zashchishchennyh chlenov ($$R.11), a takzhe funkcij-chlenov.
Esli opisany ob容kty ob容dineniya ili ukazateli na nego, to
ono ne schitaetsya bezymyannym, naprimer,
union { int aa; char* p; } obj, *ptr=&obj;
aa = 1; // oshibka
ptr->aa = 1; // normal'no
Zdes' prisvaivanie prostomu imeni aa nezakonno, t.k. imya chlena ne
privyazano ni k kakomu ob容ktu.
Inicializaciya ob容dinenij, ne imeyushchih konstruktorov, opisyvaetsya
v $$R.8.4.1.
Konstrukciya opisatel'-chlena, imeyushchaya vid,
identifikator opt : vyrazhenie-konstanta
zadaet bitovoe pole, dlina kotorogo otdelyaetsya ot ego imeni
dvoetochiem. Razmeshchenie bitovyh polej v ob容kte klassa zavisit ot
realizacii. Polya upakovyvayutsya v nekotorye adresuemye elementy
pamyati. Na odnih mashinah polya mogut vyhodit' za granicy etih
elementov, na drugih - net. Vyravnivanie bitovyh polej tozhe opredelyaetsya
realizaciej. Na odnih mashinah znacheniya pomeshchayutsya v bitovye polya
sprava nalevo, na drugih - sleva napravo.
CHtoby ustanovit' zadannoe raspolozhenie polej s pomoshch'yu dopolneniya
nulyami, ispol'zuyut bezymyannye bitovye polya. Osobyj sluchaj, kogda
ispol'zuetsya bezymyannoe pole nulevoj dliny. Ono zadaet vyravnivanie
sleduyushchego bitovogo polya po granice elementa pamyati, ispol'zuemogo
pri razmeshchenii polej.
Bezymyannoe pole ne yavlyaetsya chlenom i ne mozhet inicializirovat'sya.
Bitovye polya dolzhny imet' celochislennyj tip ($$R.3.6.1). Ih
interpretaciya zavisit ot togo, schitaetsya li znachenie polya s obychnym tipom
int (t.e. bez yavnogo ispol'zovaniya signed ili unsigned) znakovym
ili bezznakovym. Operaciya vzyatiya adresa & ne primenima k bitovym
polyam, tak chto ne mozhet byt' ni ukazatelej na bitovye polya, ni ssylok
na nih.
R.9.7 Vlozhennye opisaniya klassov
Klass mozhno opisat' v opisanii drugogo klassa. Takoj klass nazyvayut
vlozhennym. Imya vlozhennogo klassa lokal'no po otnosheniyu k
ob容mlyushchemu klassu. Vlozhennyj klass nahoditsya v oblasti vidimosti
ob容mlyushchego klassa. Esli ne schitat' yavnogo ispol'zovaniya ukazatelej,
ssylok ili imen ob容ktov, to v opisaniyah vlozhennogo klassa dopustimy
tol'ko imena tipov, staticheskih chlenov i elementov perechisleniya
iz ob容mlyushchego klassa.
int x;
int y;
class enclose {
public:
int x;
static int s;
class inner {
void f(int i)
{
x = i; // oshibka: prisvaivanie enclose::x
s = i; // normal'no: prisvaivanie enclose ::s
::x = i; // normal'no: prisvaivanie global'nomu x
y = i; // normal'no: prisvaivanie global'nomu y
}
void g(enclose* p, int i)
{
p->x = i; // normal'no: prisvaivanie enclose ::x
}
};
};
inner* p = 0; // oshibka: `inner' vne oblasti vidimosti
Funkcii-chleny vlozhennogo klassa ne imeyut osobyh prav dostupa k chlenam
ob容mlyushchego klassa, oni podchinyayutsya obychnym pravilam dostupa ($$R.11).
Analogichno, funkcii-chleny ob容mlyushchego klassa ne imeyut osobyh prav
dostupa k chlenam vlozhennogo klassa i podchinyayutsya obychnym pravilam
dostupa, naprimer:
class E {
int x;
class I {
int y;
void f(E* p, int i)
{
p->x = i; // oshibka: E::x chastnyj chlen
}
};
int g(I* p)
{
return p->y; // oshibka: I::y chastnyj chlen
}
};
Funkcii-chleny i predstavlyayushchie dannye, staticheskie chleny iz vlozhennogo
klassa mozhno opredelit' v global'noj oblasti vidimosti, naprimer:
class enclose {
class inner {
static int x;
void f(int i);
};
};
typedef enclose::inner ei;
int ei::x = 1;
void enclose::inner::f(int i) { /* ... */ }
Podobno funkcii-chlenu druzhestvennaya funkciya, opredelennaya v dannom
klasse, nahoditsya v oblasti vidimosti etogo klassa. Ona podchinyaetsya
tem zhe pravilam svyazyvaniya imen, chto i funkcii-chleny (oni ukazany vyshe
i v $$R.10.4), i ne imeet tak zhe kak oni osobyh prav dostupa k
chlenam ob容mlyushchego klassa i k lokal'nym peremennym funkcij etogo
klassa ($$R.11).
R.9.8 Opisaniya lokal'nyh klassov
Klass mozhno opisat' v opredelenii funkcii, takoj klass nazyvaetsya
lokal'nym. Imya lokal'nogo klassa schitaetsya lokal'nym v ob容mlyushchej
oblasti vidimosti, a oblast'yu vidimosti lokal'nogo klassa yavlyaetsya
ob容mlyushchaya oblast' vidimosti. V opisaniyah lokal'nogo klassa iz
ob容mlyushchej oblasti vidimosti mozhno ispol'zovat' tol'ko imena tipov,
staticheskih peremennyh, vneshnih peremennyh i funkcij, a takzhe
elementy perechisleniya. Privedem primer:
int x;
void f()
{
static int s;
int x;
extern int g();
struct local {
int h() { return x; } // oshibka: `x' avtomaticheskaya
int j() { return s; } // normal'no
int k() { return ::x; } // normal'no
int l() { return g(); } // normal'no
}
}
Ob容mlyushchaya funkciya ne imeet osobyh prav dostupa k chlenam lokal'nogo
klassa, ona podchinyaetsya obychnym pravilam dostupa ($$R.11).
Funkciyu-chlen lokal'nogo klassa sleduet opredelyat' v opredelenii etogo
klassa. Lokal'nyj klass ne mozhet imet' staticheskih chlenov,
predstavlyayushchih dannye.
R.9.9 Imena lokal'nyh tipov
Imena tipov podchinyayutsya tochno takim zhe pravilam oblastej vidimosti,
kak i drugie imena. V chastnosti, imena tipov, opredelennye v opisanii
klassa, nel'zya ispol'zovat' vne etogo klassa bez utochneniya, naprimer:
class X {
public:
typedef int I;
class Y { /* ... */ }
I a;
};
I b; // oshibka
Y c; // oshibka
X::Y d; // oshibka
Sleduyushchee polozhenie ogranichivaet zavisimost' ot konteksta pravil
opisaniya chlenov klassa, a tak zhe pravila perenosa tela funkcij,
yavlyayushchihsya podstanovkami. Posle ispol'zovaniya v opisanii klassa
imya konstanty, imya-klassa ili imya-typedef ne mozhet pereopredelyat'sya v
opisanii etogo klassa. Imya, ne yavlyayushcheesya imenem-klassa ili imenem-typedef
ne mozhet byt' opredeleno v opisanii klassa kak imya-klassa ili imya-typedef,
esli ono uzhe ispol'zovalos' inache v opisanii etogo klassa.
Rassmotrim primer:
typedef int c;
enum { i = 1 };
class X {
char v[i];
int f() { return sizeof(c); }
char c; // oshibka: imya typedef
// pereopredelyaetsya posle ispol'zovaniya
enum { i = 2 }; // oshibka: `i' pereopredelyaetsya posle
// ispol'zovaniya v zadanii tipa `char[i]'
};
typedef char* T;
struct Y {
T a;
typedef long T; // oshibka: imya T uzhe ispol'zovano
T b;
};
V opisanii klassa mozhno ukazat' spisok bazovyh klassov s pomoshch'yu
sleduyushchih konstrukcij:
spec-bazovyh:
: spisok-bazovyh
spisok-bazovyh:
specifikaciya-bazovyh
spisok-bazovyh , specifikaciya-bazovyh
specifikaciya-bazovyh:
polnoe-imya-klassa
virtual specifikaciya-dostupa opt polnoe-imya-klassa
specifikaciya-dostupa virtual opt polnoe-imya-klassa
specifikaciya-dostupa:
private
protected
public
Konstrukciya imya-klassa v specifikacii-bazovyh dolzhna oboznachat'
ranee opisannyj klass ($$R.9), kotoryj nazyvaetsya bazovym po
otnosheniyu k opredelyaemomu klassu. Govoryat, chto klass yavlyaetsya
proizvodnym ot svoih bazovyh klassov. Naznachenie konstrukcii
specifikaciya-dostupa ob座asnyaetsya v $$R.11. K chlenam bazovogo klassa,
esli tol'ko oni ne pereopredeleny v proizvodnom klasse, mozhno obrashchat'sya
tak, kak budto oni yavlyayutsya chlenami proizvodnogo klassa. Govoryat,
chto proizvodnyj klass nasleduet chleny bazovogo klassa. S pomoshch'yu
operacii razresheniya oblasti vidimosti :: ($$R.5.1) k chlenu bazovogo
klassa mozhno obrashchat'sya yavno. Takoe obrashchenie vozmozhno i v tom sluchae,
kogda imya chlena bazovogo klassa pereopredeleno v proizvodnom klasse.
Proizvodnyj klass sam mozhet vystupat' kak bazovyj pri kontrole
dostupa, sm. $$R.11.2. Ukazatel' na proizvodnyj klass mozhet neyavno
preobrazovyvat'sya v ukazatel' na odnoznachno opredelennyj i dostupnyj
bazovyj klass ($$R.4.6). Ssylka na proizvodnyj klass mozhet neyavno
preobrazovyvat'sya v ssylku na odnoznachno opredelennyj i dostupnyj
bazovyj klass ($$R.4.7).
Rassmotrim primer:
class base {
public:
int a, b;
};
class derived : public base {
public:
int b, c;
};
void f()
{
derived d;
d.a = 1;
d.base::b = 2;
d.b = 3;
d.c = 4;
base* bp = &d; // standartnoe preobrazovanie derived* v base*
}
Zdes' prisvaivayutsya znacheniya chetyrem chlenam d, a bp nastraivaetsya
na d.
Klass nazyvaetsya pryamym bazovym, esli on nahoditsya v spiske-bazovyh,
i kosvennym bazovym, esli sam ne yavlyayas' pryamym bazovym, on sluzhit
bazovym dlya odnogo iz klassov spiska-bazovyh.
Otmetim, chto v oboznachenii imya-klassa :: imya konstrukciya, imya mozhet
byt' imenem chlena kosvennogo bazovogo klassa. Takoe oboznachenie
prosto ukazyvaet klass, v kotorom sleduet nachinat' poisk etogo imeni.
Privedem primer:
class A { public: void f(); }
class B : public A { };
class C : public B { public: void f(); }
void C::f()
{
f(); // vyzov f() iz C
A::f(); // vyzov f() iz A
B::f(); // vyzov f() iz A
}
Zdes' dvazhdy vyzyvaetsya A::f(), poskol'ku eto edinstvennaya funkciya f()
v klasse B.
Inicializaciya ob容ktov, predstavlyayushchih bazovye klassy, zadaetsya
v konstruktorah, sm. $$R.12.6.2.
R.10.1 Mnozhestvennye bazovye klassy
Klass mozhet byt' proizvodnym po otnosheniyu k lyubomu chislu bazovyh
klassov. Privedem primer:
class A { /* ... */ };
class B { /* ... */ };
class C { /* ... */ };
class D : public A, public B, public C { /* ... */ };
Ispol'zovanie bolee, chem odnogo pryamogo bazovogo klassa nazyvaetsya
mnozhestvennym nasledovaniem.
Poryadok nasledovaniya ne vazhen, esli ne uchityvat' voprosov,
svyazannyh so standartnoj inicializaciej s pomoshch'yu konstruktora
($$R.12.1), unichtozheniem ($$R.12.4) i razmeshcheniem v pamyati
($$r.5.4, $$R.9.2, $$R.11.1). Poryadok vydeleniya pamyati dlya bazovyh
klassov opredelyaetsya realizaciej.
Nel'zya ukazyvat' klass v kachestve pryamogo bazovogo po otnosheniyu
k proizvodnomu klassu bolee odnogo raza, no kosvennym bazovym klassom
on mozhet byt' neodnokratno.
class B { /* ... */ };
class D : public B, public B { /* ... */ }; // nedopustimo
class L { /* ... */ };
class A : public L { /* ... */ };
class B : public L { /* ... */ };
class C : public A, public B { /* ... */ }; // normal'no
Zdes' ob容kt klassa C budet imet' dva vlozhennyh ob容kta klassa L.
K specifikacii bazovogo klassa mozhno dobavit' sluzhebnoe slovo
virtual. Otdel'nyj ob容kt virtual'nogo bazovogo klassa V razdelyaetsya
mezhdu vsemi bazovymi klassami, kotorye ukazali V pri zadanii svoih
bazovyh klassov. Privedem primer:
class V { /* ... */ };
class A : virtual public V { /* ... */ };
class B : virtual public V { /* ... */ };
class C : public A, public B { /* ... */ };
Zdes' ob容kt klassa C budet imet' tol'ko odin vlozhennyj ob容kt
klassa V.
Klass mozhet soderzhat' virtual'nye i nevirtual'nye bazovye klassy odnogo
tipa, naprimer:
class B { /* ... */ };
class X : virtual public B { /* ... */ };
class Y : virtual public B { /* ... */ };
class Z : public B { /* ... */ };
class AA : public X, public Y, public Z { /* ... */ };
Zdes' ob容kt klassa AA budet imet' dva vlozhennyh ob容kta klassa B:
iz klassa Z i virtual'nyj, razdelyaemyj mezhdu klassami X i Y.
R.10.1.1 Neodnoznachnosti
Dostup k bazovomu klassu dolzhen byt' zadan odnoznachno. Dostup k
chlenu bazovogo klassa schitaetsya neodnoznachnym, esli vyrazhenie,
ispol'zuemoe dlya dostupa, zadaet bolee odnoj funkcii, ob容kta,
tipa ili elementa perechisleniya. Proverka na odnoznachnost' proishodit
do proverki vozmozhnosti dostupa ($$R.11). Privedem primer:
class A {
public:
int a;
int (*b)();
int f();
int f(int);
int g();
};
class B {
int a;
int b();
public:
int f();
int g();
int h();
int h(int);
};
class C : public A, public B { };
void g(C* pc)
{
pc->a = 1; // oshibka: neodnoznachnost': A::a ili B::a
pc->b(); // oshibka: neodnoznachnost': A::b ili B::b
pc->f(); // oshibka: neodnoznachnost': A::f ili B::f
pc->f(1); // oshibka: neodnoznachnost': A::f ili B::f
pc->g(); // oshibka: neodnoznachnost': A::g ili B::g
pc->g = 1; // oshibka: neodnoznachnost': A::g ili B::g
pc->h(); // normal'no
pc->h(1); // normal'no
}
Esli imya peregruzhennoj funkcii ustanovleno odnoznachno, to prezhde
proverki vozmozhnosti dostupa proishodit eshche i razreshenie peregruzki.
Neodnoznachnost' mozhno ustranit', utochnyaya ispol'zuemoe imya imenem
klassa, naprimer, tak:
class A {
public:
int f();
};
class B {
public:
int f();
};
class C : public A, public B {
int f() { return A::f() + B::f(); }
};
Esli ispol'zuyutsya virtual'nye bazovye klassy, do otdel'noj funkcii,
ob容kta, tipa ili elementa perechisleniya mozhno dobrat'sya neskol'kimi
putyami, dvigayas' po napravlennomu aciklichnomu grafu, kotoryj
obrazuyut bazovye klassy. No eto ne yavlyaetsya neodnoznachnost'yu.
Identichnoe zhe ispol'zovanie nevirtual'nyh bazovyh klassov
porozhdaet neodnoznachnost', poskol'ku v etom sluchae uchastvuet v
zadanii dostupa bolee odnogo vlozhennogo ob容kta. Privedem primer:
class V { public: int v; };
class A { public: int a; };
class B : public A, public virtual V { };
class C : public A, public virtual V { };
class D : public B, public C { public: void f(); };
void D::f()
{
v++; // normal'no
a++; // oshibka, neodnoznachnost': `a' v `D' vhodit dvazhdy
}
Esli ispol'zuyutsya virtual'nye bazovye klassy, vozmozhno chto
dvigayas' po napravlennomu aciklichnomu grafu, mozhno dobrat'sya bolee,
chem do odnogo imeni funkcii, ob容kta ili elementa perechisleniya. |to,
konechno, neodnoznachnost', no krome sluchaya, kogda odno imya dominiruet
nad drugimi. Identichnoe ispol'zovanie nevirtual'nyh bazovyh klassov
vsegda privodit k neodnoznachnosti, t.k. v etom sluchae vsegda uchastvuet
bolee odnogo vlozhennogo ob容kta.
Schitaetsya, chto imya B::f dominiruet nad imenem A::f, esli klass
A yavlyaetsya dlya klassa B bazovym. Esli odno imya dominiruet nad
drugim, oni ne mogut privesti k neodnoznachnosti: v situacii vybora
ispol'zuetsya vsegda dominiruyushchee imya. Privedem primer:
class V { public: int f(); int x; };
class B : public virtual V { public: int f(); int x; };
class C : public virtual V { };
class D : public B, public C { void g(); };
void D::g()
{
x++; // normal'no: B::x dominiruet nad V::x
f(); // normal'no: B::f() dominiruet nad V::f()
}
V rezul'tate yavnogo ili neyavnogo preobrazovaniya ukazatelya ili ssylki
na proizvodnyj klass v ukazatel' ili ssylku na odin iz ego bazovyh
klassov, eti ukazatel' ili ssylka dolzhny ukazyvat' tol'ko na tot
zhe samyj ob容kt, kotoryj predstavlyaet bazovyj klass. Privedem primer:
class V { };
class A { };
class B : public A, public virtual V { };
class C : public A, public virtual V { };
class D : public B, public C { };
void g()
{
D d;
B* pb = &d;
A* pa = &d; // oshibka, neodnoznachnost': A iz C ili A iz B?
v* pv = &d; // normal'no: tol'ko odin vlozhennyj ob容kt V
}
R.10.2 Virtual'nye funkcii
Esli klass base soderzhit virtual'nuyu ($$R.7.1.2) funkciyu vf, a
proizvodnyj ot nego klass derived takzhe soderzhit funkciyu vf togo
zhe tipa, togda vyzov vf dlya ob容kta klassa derived yavlyaetsya
obrashcheniem k derived::vf, dazhe esli dostup k etoj funkcii proishodit
cherez ukazatel' ili ssylku na klass base. Govoryat, chto funkciya
proizvodnogo klassa podavlyaet funkciyu bazovogo klassa. Odnako, esli
tipy funkcij ($$R.8.2.5) razlichny, funkcii schitayutsya raznymi i mehanizm
virtual'nosti ne dejstvuet (sm. takzhe $$R.13.1). Schitaetsya oshibkoj,
esli funkciya proizvodnogo klassa otlichaetsya ot virtual'noj funkcii
bazovogo klassa tol'ko tipom vozvrashchaemogo znacheniya. Rassmotrim
primer:
struct base {
virtual void vf1();
virtual void vf2();
virtual void vf3();
void f();
};
class derived : public base {
public:
void vf1();
void vf2(int); // skryvaet base::vf2()
char vf3(); // oshibka: razlichie tol'ko v tipe
// vozvrashchaemogo znacheniya
}
void g()
{
derived d;
base* bp = &d; // standartnoe preobrazovanie: derived* v base*
bp->vf1(); // vyzov derived::vf1
bp->vf2(); // vyzov base::vf2
bp->f(); // vyzov base::f
}
Zdes' tri vyzova dlya ob容kta d klassa derived privedut k obrashcheniyam k
derived::vf1, base::vf2 i base::f sootvetstvenno. Inymi slovami,
interpretaciya vyzova virtual'noj funkcii zavisit ot tipa ob容kta,
dlya kotorogo ona vyzyvaetsya, togda kak interpretaciya vyzova
nevirtual'noj funkcii-chlena zavisit tol'ko ot tipa ukazatelya ili
ssylki na etot ob容kt. Naprimer, vyrazhenie bp->vf1()
privedet k vyzovu derived::vf1(), poskol'ku bp ukazyvaet na ob容kt
klassa derived, v kotorom funkciya derived::vf1() podavlyaet
virtual'nuyu funkciyu base::vf1().
Nalichie specifikacii virtual oznachaet, chto funkciya yavlyaetsya chlenom,
poetomu virtual'naya funkciya ne mozhet byt' global'noj funkciej (ne chlenom)
($$R.7.1.2). Tochno tak zhe virtual'naya funkciya ne mozhet byt'
staticheskim chlenom, t.k. dlya vyzova virtual'noj funkcii neobhodimo
nalichie opredelennogo ob容kta, kotoryj ukazyvaet, kakuyu funkciyu
nado vyzyvat'. V drugom klasse virtual'nuyu funkciyu mozhno opisat' kak
druga. Funkciya, podavlyayushchaya virtual'nuyu, sama schitaetsya virtual'noj
funkciej. Specifikaciyu virtual mozhno ispol'zovat' dlya podavlyayushchej
funkcii proizvodnogo klassa, no eto izbytochno. Virtual'naya funkciya
mozhet byt' opredelena ili opisana v bazovom klasse kak chistaya
($$R.10.3). Virtual'nuyu funkciyu, kotoraya opredelena v bazovom klasse,
ne nuzhno opredelyat' v proizvodnom klasse: pri vseh vyzovah budet
ispol'zovat'sya funkciya, opredelennaya v bazovom klasse.
Mehanizm virtual'nosti pri vyzove otklyuchaetsya, esli est' yavnoe
utochnenie imeni s pomoshch'yu operatora razresheniya oblasti vidimosti
($$R.5.1), naprimer:
class B { public: virtual void f(); };
class D : public B { public: void f(); };
void D::f() { /* ... */ B::f(); }
Zdes' obrashchenie k f iz D privodit k vyzovu B::f, a ne D::f.
R.10.3 Abstraktnye klassy
Abstraktnye klassy dayut sredstvo dlya predstavleniya v yazyke obshchih
ponyatij, takih, naprimer, kak figura, dlya kotoryh mogut ispol'zovat'sya
tol'ko konkretnye ih varianty, naprimer, krug ili kvadrat. Krome togo
abstraktnyj klass pozvolyaet zadat' interfejs, raznoobraznye realizacii
kotorogo predstavlyayut proizvodnye klassy.
Abstraktnym nazyvaetsya klass, kotoryj mozhno ispol'zovat' tol'ko
kak bazovyj dlya nekotorogo drugogo klassa, t.e. nel'zya sozdat'
nikakogo ob容kta abstraktnogo klassa krome togo, kotoryj predstavlyaet
bazovyj klass dlya nekotorogo proizvodnogo klassa. Klass schitaetsya
abstraktnym, esli v nem est' hotya by odna chistaya virtual'naya
funkciya. Pri opisanii klassa virtual'naya funkciya opisyvaetsya kak
chistaya s pomoshch'yu specifikacii-chistoj ($$R.9.2). CHistuyu virtual'nuyu
funkciyu ne nuzhno opredelyat', esli tol'ko ona yavno ne vyzyvaetsya
s pomoshch'yu konstrukcii utochnennoe-imya ($$R.5.1). Rassmotrim primer:
class point { /* ... */ };
class shape { // abstraktnyj klass
point center;
// ...
public:
point where() { return center; }
void move(point p) { center=p; draw(); }
virtual void rotate(int) = 0; // chistaya virtual'naya
virtual void draw() = 0; // chistaya virtual'naya
// ...
};
Abstraktnyj klass nel'zya ispol'zovat' kak tip formal'nogo parametra,
tip vozvrashchaemogo znacheniya, a takzhe kak tip v operacii yavnogo
preobrazovaniya tipa. Mozhno opisyvat' ukazateli i ssylki na abstraktnyj
klass, naprimer:
shape x; // oshibka: ob容kt abstraktnogo klassa
shape* p; // normal'no
shape f(); // oshibka
void g(shape); // oshibka
shape& h(shape&); // normal'no
CHistye virtual'nye funkcii i nasleduyutsya kak chistye virtual'nye
funkcii, naprimer:
class ab_circle : public shape {
int radius;
public:
void rotate(int) { }
// ab_circle::draw() chistaya virtual'naya funkciya
};
Poskol'ku funkciya shape::draw() yavlyaetsya chistoj virtual'noj funkciej,
to takoj zhe budet po opredeleniyu i funkciya ab_circle::draw(). Dlya
privedennogo nizhe opisaniya klass circle ne budet abstraktnym, i u
funkcii circle::draw() gde-to dolzhno sushchestvovat' opredelenie.
class circle : public shape {
int radius:
public:
void rotate(int) { }
void draw(); // dolzhna byt' gde-to opredelena
};
Funkcii-chleny mozhno vyzyvat' iz konstruktora abstraktnogo klassa,
rezul'tat pryamogo ili kosvennogo vyzova chistoj virtual'noj funkcii
dlya ob容kta, sozdannogo s pomoshch'yu takogo konstruktora, neopredelen.
R.10.4 Svodka pravil oblasti vidimosti
Teper' mozhno svesti voedino pravila oblastej vidimosti dlya programmy
na S++. |ti pravila odinakovo primenimy dlya vseh imen (vklyuchaya
imya-typedef ($$R.7.1.3) i imya-klassa ($$R.9.1)) i v lyubom
kontekste, dlya kotorogo oni dopustimy po sintaksisu yazyka. Zdes'
rassmatrivayutsya tol'ko oblasti vidimosti na leksicheskom urovne,
voprosy svyazyvaniya obsuzhdayutsya v $$R.3.3. Ponyatie momenta opisaniya
bylo vvedeno v $$R.3.2.
Vsyakoe ispol'zovanie imeni dolzhno byt' odnoznachnym (ne schitaya
peregruzki) v oblasti ego vidimosti ($$R.10.1.1). Pravila dostupa
($$R.11) nachinayut dejstvovat' tol'ko togda, kogda imya mozhno odnoznachno
najti v oblasti ego vidimosti. Tol'ko pri uslovii, chto prava dostupa
k imeni ne narusheny, nachinaetsya proverka tipa ob容kta, funkcii ili
elementa perechisleniya.
Imya, kotoroe ispol'zuetsya vne lyuboj funkcii ili klassa, ili pered
kotorym stoit unarnaya operaciya razresheniya oblasti vidimosti ::
(i kotoroe ne utochnyaetsya binarnoj operaciej :: ili operaciyami ->
ili .), dolzhno byt' imenem global'nogo ob容kta, ili funkcii, ili
elementa perechisleniya, ili tipa.
Imya, zadavaemoe posle X:: ili obj., gde obj tipa X ili tipa
ssylka na X, a takzhe imya, zadavaemoe posle ptr->, gde ptr tipa ukazatel'
na X, dolzhno byt' imenem chlena klassa X ili chlenom bazovogo po
otnosheniyu k X klassa. Pomimo etogo, v obrashchenii ptr->imya ptr mozhet
byt' ob容ktom klassa Y, v kotorom est' funkciya operator->(),
opisannaya takim obrazom, chto ptr->operator() v konechnom schete
okazyvaetsya ukazatelem na X ($$R.13.4.6).
Imya, kotoroe ne utochnyaetsya odnim iz opisannyh vyshe sposobov, i,
kotoroe ispol'zuetsya v funkcii, ne yavlyayushchejsya chlenom klassa,
dolzhno byt' opisano v tom bloke, gde ono ispol'zuetsya, ili v
ob容mlyushchem bloke ili dolzhno byt' global'nym. Opisanie lokal'nogo imeni
skryvaet opisaniya togo zhe imeni v ob容mlyushchih blokah, a takzhe ego
opisaniya kak global'nogo imeni. V chastnosti, peregruzka imeni
nevozmozhna dlya imen v raznyh oblastyah vidimosti ($$R.13.4).
Imya, kotoroe ne utochnyaetsya odnim iz opisannyh vyshe sposobov, i,
kotoroe ispol'zuetsya v funkcii, yavlyayushchejsya nestaticheskim chlenom
klassa X, dolzhno byt' opisano ili v tom bloke, gde ono ispol'zuetsya,
ili v ob容mlyushchem bloke, i ono dolzhno byt' chlenom klassa X, ili
chlenom bazovogo po otnosheniyu k X klassa, ili eto imya dolzhno byt'
global'nym. Opisanie lokal'nyh imen skryvaet opisanie etih zhe imen
v ob容mlyushchih blokah, v chlenah klassa etoj funkcii i sredi global'nyh
imen. Opisanie chlena skryvaet analogichnye opisanie s tem zhe imenem
v bazovyh klassah i sredi global'nyh imen.
Imya, kotoroe ne utochnyaetsya odnim iz opisannyh vyshe sposobov, i,
kotoroe ispol'zuetsya v staticheskoj funkcii-chlene klassa X, dolzhno
byt' opisano ili v tom bloke, gde ono ispol'zuetsya, ili v ob容mlyushchem
bloke, i dolzhno byt' staticheskim chlenom klassa X, ili bazovogo po
otnosheniyu k X klassa, ili ono dolzhno byt' global'nym imenem.
Imya formal'nogo parametra funkcii, zadannoe pri ee opredelenii
($$R.8.3), prinadlezhit oblasti vidimosti, sovpadayushchej s naibol'shim
blokom funkcii (v chastnosti, yavlyaetsya lokal'nym imenem). Imya
formal'nogo parametra funkcii, zadannoe v ee opisanii ($$R.8.2.5),
a ne opredelenii, prinadlezhit lokal'noj oblasti vidimosti, kotoraya
ischezaet srazu zhe posle opisaniya funkcii. Standartnye znacheniya
parametrov nahodyatsya v oblasti vidimosti, opredelyaemoj v moment
opisaniya ($$R.3.2) formal'nyh parametrov funkcii; v nih ne dolzhny
ispol'zovat'sya lokal'nye peremennye ili nestaticheskie chleny klassa,
i oni vychislyayutsya pri kazhdom vyzove funkcii ($$R.8.2.6).
Inicializator-ctor ($$R.12.6.2) vychislyaetsya v oblasti vidimosti
naibol'shego bloka konstruktora, dlya kotorogo on zadan. V chastnosti,
v nem mozhno ispol'zovat' imena formal'nyh parametrov.
R.11 Kontrol' dostupa k chlenam
CHlen klassa mozhet byt':
chastnym (private); eto znachit, chto ego imya mozhno ispol'zovat'
tol'ko v funkciyah-chlenah i druz'yah klassa, v kotorom on opisan;
zashchishchennym (protected); eto znachit, chto ego imya mozhno ispol'zovat'
tol'ko v funkciyah-chlenah i druz'yah klassa, v kotorom on opisan,
a takzhe v funkciyah-chlenah i druz'yah klassov, yavlyayushchihsya
proizvodnymi po otnosheniyu k etomu klassu (sm. $$R.11.5);
obshchim (public); eto znachit, chto ego imya mozhno ispol'zovat'
v lyuboj funkcii.
CHleny klassa, opisannogo so sluzhebnym slovom class, yavlyayutsya
chastnymi po opredeleniyu. CHleny klassa, opisannogo so sluzhebnym
slovom struct ili union, yavlyayutsya obshchimi po opredeleniyu, naprimer:
class X {
int ; // X:: chastnyj po opredeleniyu
};
struct S {
int a; // S::a obshchij po opredeleniyu
};
R.11.1 Specifikacii dostupa
Opisaniya chlenov mogut byt' snabzheny specifikaciej dostupa ($$R.10):
specifikaciya-dostupa : spisok-chlenov opt
Specifikaciya-dostupa zadaet pravila dostupa k chlenam, kotorye
dejstvuyut do konca zhizni klassa ili poka ne poyavitsya drugaya
specifikaciya-dostupa, naprimer,
class X {
int a; // X::a chastnyj po opredeleniyu: uchityvaetsya 'class'
public:
int b; // X::b obshchij
int c; // X::c obshchij
};
Dopustimo lyuboe chislo specifikacij dostupa i zadavat' ih mozhno v
lyubom poryadke, naprimer,
struct S {
int a; // S::a obshchij po opredeleniyu: uchityvaetsya `struct'
protected:
int b; // S::b zashchishchennyj
private:
int c; // S::c chastnyj
public:
int d; // S:: d obshchij
};
Poryadok razmeshcheniya chlenov, predstavlyayushchih dannye, kotorye imeyut
raznye specifikacii-dostupa, opredelyaetsya realizaciej ($$R.9.2).
R.11.2 Specifikacii dostupa dlya bazovyh klassov
Esli klass opisan kak bazovyj ($$r.10) po otnosheniyu k
drugomu klassu s pomoshch'yu specifikacii dostupa public, to chleny so
specifikaciej public ili protected iz bazovogo klassa yavlyayutsya
sootvetstvenno chlenami s toj zhe specifikaciej dlya proizvodnogo klassa.
Esli klass opisan kak bazovyj po otnosheniyu k drugomu s pomoshch'yu
specifikacii dostupa private, to chleny so specifikaciej public ili
protected iz bazovogo klassa yavlyayutsya chlenami so specifikaciej
private dlya proizvodnogo klassa. CHastnye chleny bazovogo klassa
ostayutsya nedostupnymi dazhe dlya proizvodnyh klassov, esli tol'ko dlya
obespecheniya dostupa pri opisanii bazovogo klassa ne bylo ispol'zovano
opisanie friend.
Esli dlya bazovogo klassa ne ukazana specifikaciya-dostupa, to
dlya proizvodnogo klassa, esli on opisan kak struct, predpolagaetsya
specifikaciya public, a esli on opisan so sluzhebnym slovom
class, to - specifikaciya private, naprimer:
class B { /* ... */ };
class D1 : private B { /* ... */ };
class D2 : public B { /* ... */ };
class D3 : B { /* ... */ }; // `B' chastnyj po opredeleniyu
struct D4 : public B { /* ... */ };
struct D5 : private B { /* ... */ };
struct D6 : B { /* ... */ }; // `B' chastnyj po opredeleniyu
Zdes' klass yavlyaetsya obshchim (public) bazovym klassom dlya D2, D4 i D6
i chastnym (private) bazovym klassom dlya D1, D2 i D5.
Opisanie bazovogo klassa kak private ne vliyaet na dostup k
staticheskim chlenam bazovogo klassa. Odnako, esli pri obrashchenii k
staticheskomu chlenu ispol'zuetsya ob容kt ili ukazatel', kotoryj
nuzhno preobrazovyvat', to dejstvuyut obychnye pravila preobrazovaniya
ukazatelej.
V funkciyah-chlenah ili druz'yah klassa X mozhno X* neyavno
preobrazovyvat' v ukazatel' na chastnyj klass, yavlyayushchijsya
neposredstvenno bazovym po otnosheniyu k X.
Ispol'zuya utochnennoe imya, mozhno ustanovit' dostup k chlenu bazovogo
klassa v chasti public ili protected opisaniya proizvodnogo klassa.
|to nazyvaetsya opisaniem dostupa.
Privedem primer:
class B {
int a;
public:
int b, c;
int bf();
};
class D : private B {
int d;
public:
B::c; // adjust access to `B::c'
int e;
int df();
};
int ef(D&);
Vo vneshnej funkcii ef mozhno ispol'zovat' tol'ko imena c, e, i df.
Poskol'ku funkciya df chlen klassa D, v nej mozhno ispol'zovat'
imena b, c, bf, d, e i df, no ne a. Funkciya bf - chlen klassa B i
v nej mozhno ispol'zovat' chleny a, b, c i bf.
Opisaniya dostupa ne sleduet ispol'zovat' dlya ogranicheniya dostupa
k chlenu, dostupnomu v bazovom klasse, takzhe kak ne sleduet
ispol'zovat' ego dlya obespecheniya dostupa k chlenu, kotoryj nedostupen
v bazovom klasse, naprimer:
class B {
public:
int a;
private:
int b;
protected:
int c;
};
class D : private B {
public:
B::a; // opisat' `a' kak obshchij chlen D
B::b; // oshibka: popytka rasshirit' dostup,
// `b' ne mozhet byt' obshchim chlenom D
protected:
B::c; // opisat' `c' kak zashchishchennyj chlen D
B::a; // oshibka: popytka suzit' dostup,
// `a' ne mozhet byt' zashchishchennym chlenom D
};
Opisanie dostupa dlya imeni peregruzhennoj funkcii ustanavlivaet
dostup v bazovom klasse ko vsem funkciyam s etim imenem, naprimer:
class X {
public:
f();
f(int);
};
class Y : private X {
public:
X::f; // makes X::f() and X::f(int) public in Y
};
Nel'zya v proizvodnom klasse ustanovit' dostup k chlenu bazovogo
klassa, esli v proizvodnom klasse opredelen chlen s etim zhe imenem,
naprimer:
class X {
public:
void f();
};
class Y : private X {
public:
void f(int);
X::f; // oshibka: dva opisaniya f
};
Drugom klassa nazyvaetsya funkciya, kotoraya ne yavlyaetsya chlenom klassa,
no v kotoroj mozhno ispol'zovat' chastnye i zashchishchennye chleny etogo
klassa. Imya druga ne prinadlezhit oblasti vidimosti klassa, i
druzhestvennaya funkciya ne vyzyvaetsya s pomoshch'yu operacij dostupa k
chlenam ($$R.5.2.4), esli tol'ko ona ne yavlyaetsya chlenom drugogo
klassa. Sleduyushchij primer pokazyvaet razlichie mezhdu chlenami i
druz'yami:
class X {
int a;
friend void friend_set(X*, int);
public:
void member_set(int);
};
void friend_set(X* p, int i) { p->a = i; }
void X::member_set(int i) { a = i; }
void f()
{
X obj;
friend_set(&obj,10);
obj.member_set(10);
}
Esli v opisanii friend ispol'zovano imya peregruzhennoj funkcii
ili operacii, tol'ko funkciya, odnoznachno opredelyaemaya tipami
formal'nyh parametrov, stanovitsya drugom. Funkciya-chlen klassa X
mozhet byt' drugom klassa Y, naprimer:
class Y {
friend char* X::foo(int);
// ...
};
Mozhno ob座avit' vse funkcii klassa X druz'yami klassa Y s pomoshch'yu
specifikacii-slozhnogo-tipa ($$R.9.1):
class Y {
friend class X;
// ...
};
Opisanie odnogo klassa kak drug drugogo klassa dopolnitel'no
podrazumevaet, chto chastnye i zashchishchennye chleny klassa, predlagayushchego
druzhbu, mogut ispol'zovat'sya v klasse, poluchayushchem ee, naprimer:
class X {
enum { a=100 };
friend class Y;
};
class Y {
int v[X::a]; // Y drug klassa X
};
class Z {
int v[X::a]; // oshibka: X::a nedostupno
};
Esli klass ili funkciya, ob座avlennye kak druz'ya, ne byli opisany,
ih imena popadayut v tu zhe oblast' vidimosti, chto i imya klassa,
soderzhashchego opisanie friend ($$R.9.1).
Funkciya, poyavivshayasya pervyj raz v opisanii friend, schitaetsya
ekvivalentnoj funkcii, opisannoj kak extern ($$R.3.3, $$r.7.1.1).
Esli funkciya-drug opredelena v opisanii klassa, ona schitaetsya
funkciej so specifikaciej inline i k nej primenimo pravilo
perenosa opredeleniya funkcii dlya funkcij-chlenov ($$R.9.3.2).
Funkciya-drug, opredelennaya v opisanii klassa, otnositsya na
leksicheskom urovne k oblasti vidimosti etogo klassa. Dlya
funkcii-druga, opredelennoj vne klassa, eto ne tak.
Na opisanie friend ne vliyaet ukazanie specifikacij-dostupa
($$R.9.2).
Ponyatie druzhby ne yavlyaetsya ni nasleduemym, ni tranzitivnym.
Podtverdim eto primerom:
class A {
friend class B;
int a;
};
class B {
friend class C;
};
class C {
void f(A* p);
{
p->a++; // oshibka: C ne drug klassa A, hotya
// yavlyaetsya drugom druga klassa A
}
};
class D : public B {
void f(A* p)
{
p->a++; // oshibka: D ne drug klassa A, hotya
// yavlyaetsya proizvodnym druga klassa A
}
};
R.11.5 Dostup k zashchishchennym chlenam
Drug ili funkciya-chlen proizvodnogo klassa imeet dostup k zashchishchennomu
staticheskomu chlenu bazovogo klassa. Drug ili funkciya-chlen proizvodnogo
klassa mogut poluchit' dostup k zashchishchennomu nestaticheskomu chlenu
odnogo iz svoih bazovyh klassov tol'ko cherez ukazatel', ssylku ili
ob容kt proizvodnogo klassa (ili lyubogo klassa, yavlyayushchegosya
proizvodnym po otnosheniyu k nemu). Rassmotrim primer:
class B {
protected:
int i;
};
class D1 : public B {
};
class D2 : public B {
friend void fr(B*, D1*, D2*);
void mem(B*, D1*);
};
void fr(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // nedopustimo
p1->i = 2; // nedopustimo
p2->i = 3; // normal'no (obrashchenie cherez D2)
}
void D2::mem(B* pb, D1* p1)
{
pb->i = 1; // nedopustimo
p1->i = 2; // nedopustimo
i = 3; // normal'no (obrashchenie cherez this)
}
void g(B* pb, D1* p1, D2* p2)
{
pb->i = 1; // nedopustimo
p1->i = 2; // nedopustimo
p2->i = 3; // nedopustimo
}
R.11.6 Dostup k virtual'nym funkciyam
Pravila dostupa ($$r.11) k virtual'noj funkcii opredelyayutsya ee
opisaniem i na nih ne vliyayut pravila dostupa k k funkcii, kotoraya
pozdnee budet podavlyat' ee. Privedem primer:
class B {
public:
virtual f();
};
class D : public B {
private:
f();
};
void f()
{
D d;
B* pb = &d;
D* pd = &d;
pb->f(); // normal'no: B::f() obshchij chlen
// vyzyvaetsya D::f()
pd->f(); // oshibka: D::f() chastnyj chlen
}
Prava dostupa proveryayutsya pri samom vyzove, ispol'zuya tip vyrazheniya,
oboznachayushchee ob容kt, dlya kotorogo vyzyvaetsya funkciya-chlen (v primere
vyshe eto B*). Dostup k funkcii-chlenu v klasse, gde ona opredelena
(D v primere vyshe), v obshchem sluchae neizvesten.
R.11.7 Mnozhestvennyj dostup
Esli dobrat'sya do imeni mozhno neskol'kimi putyami po grafu, zadayushchemu
mnozhestvennoe nasledovanie, to pravo dostupa etogo imeni schitaetsya
maksimal'nym iz prav, poluchaemyh na raznyh putyah. Poyasnim eto
primerom:
class W { public: void f(); };
class A : private virtual W { };
class B : public virtual W { };
class C : public A, public B {
void f() { W::f(); } // normal'no
};
Poskol'ku W::f() dostupno v C::f() po puti, svyazannomu s obshchim
nasledovaniem iz B, obrashchenie yavlyaetsya zakonnym.
R.12 Special'nye funkcii-chleny
Nekotorye funkcii-chleny schitayutsya special'nymi, poskol'ku oni
vliyayut na to, kak ob容kty klassa sozdayutsya, kopiruyutsya i unichtozhayutsya,
i kak znacheniya odnogo tipa preobrazuyutsya v znacheniya drugogo tipa.
CHasto takie funkcii vyzyvayutsya neyavno.
|ti funkcii-chleny podchinyayutsya obychnym pravilam dostupa ($$R.11).
Naprimer, opisanie konstruktora so specifikaciej protected
garantiruet, chto sozdavat' ob容kty s ego pomoshch'yu smogut tol'ko
proizvodnye klassy i druz'ya.
Konstruktorom nazyvaetsya funkciya-chlen, imya kotoroj sovpadaet s imenem
klassa, on ispol'zuetsya dlya postroeniya znachenij, imeyushchih tip dannogo
klassa. Esli v klasse est' konstruktor, to kazhdyj ob容kt etogo klassa
pered proizvol'nym ispol'zovaniem budet inicializirovat'sya, sm.
$$R.12.6.
Konstruktor mozhet vyzyvat'sya dlya ob容kta so specifikaciej const
ili volatile. Sam konstruktor nel'zya opisyvat' so specifikaciej
const ili volatile ($$R.9.3.1). Konstruktor takzhe ne mozhet imet'
specifikaciyu virtual ili static.
Konstruktory ne nasleduyutsya, odnako, standartnye konstruktory
i konstruktory kopirovaniya pri neobhodimosti sozdayutsya translyatorom
($$R.12.8). Takie konstruktory yavlyayutsya obshchimi.
Standartnym konstruktorom dlya klassa X yavlyaetsya takoj konstruktor
klassa X, kotoryj mozhno vyzyvat' bez parametrov. Standartnyj
konstruktor dlya klassa X budet sozdan tol'ko togda, kogda dlya klassa
X ne opisano ni odnogo konstruktora.
Konstruktorom kopirovaniya dlya klassa X nazyvaetsya konstruktor,
kotoryj vyzyvaetsya dlya kopirovaniya ob容kta klassa X, t.e. vyzyvaetsya
s odnim parametrom tipa X. Naprimer, X::X(const X&) i
X::X(X&, int=0) yavlyayutsya konstruktorami kopirovaniya. Konstruktor
kopirovaniya sozdaetsya tol'ko togda, kogda ne opisano ni odnogo
konstruktora kopirovaniya.
Konstruktor kopirovaniya dlya klassa X ne dolzhen imet' v kachestve
parametra ob容kt tipa X, naprimer X::X(X) nezakonnoe obrashchenie.
Konstruktor dlya massiva elementov vyzyvaetsya v poryadke
vozrastaniya adresov elementov ($$R.8.2.4).
Esli u klassa est' bazovye klassy s konstruktorom ili chleny,
yavlyayushchiesya ob容ktami s konstruktorom, ih konstruktory vyzyvayutsya
prezhde, chem konstruktor proizvodnogo klassa. V $$R.12.6.2 ob座asnyaetsya
kak zadayutsya parametry dlya takih konstruktorov i kak opredelyaetsya
poryadok ih vyzova.
Ob容kt klassa s konstruktorom ne mozhet byt' chlenom ob容dineniya.
Dlya konstruktora ne nuzhno ukazyvat' nikakogo tipa vozvrashchaemogo
znacheniya, dazhe void. V operatore return v tele konstruktora nel'zya
ukazyvat' vozvrashchaemoe znachenie. Ne dopustima operaciya vzyatiya
adresa konstruktora.
Konstruktor mozhno yavno ispol'zovat' dlya sozdaniya ob容ktov ego
tipa s pomoshch'yu sleduyushchej zapisi:
imya-klassa ( spisok-vyrazhenij opt )
Privedem primer:
complex zz = complex(1,2.3);
print( complex(7.8,1.2) );
Ob容kt, sozdannyj takim obrazom yavlyaetsya bezymyannym (esli tol'ko
konstruktor ne ispol'zovalsya dlya inicializacii poimenovannoj peremennoj
kak zz vyshe), a vremya ego zhizni ogranicheno vyrazheniem, v kotorom
on byl sozdan, sm. $$R.12.2.
V konstruktore mozhno vyzyvat' funkciyu-chlen, sm. $$R.12.7.
V nekotoryh situaciyah translyatoru byvaet neobhodimo ili udobno
sozdavat' vremennye ob容kty. Ispol'zovanie vremennyh ob容ktov
zavisit ot realizacii. Esli translyatoru ponadobilsya vremennyj
ob容kt tipa klassa s konstruktorom, on dolzhen obespechit' vyzov
konstruktora dlya etogo vremennogo ob容kta. Analogichno, neobhodimo
vyzyvat' destruktor dlya ob容kta klassa, v kotorom opisan
destruktor. Privedem primer:
class X {
// ...
public:
// ...
X(int);
X(X&);
~X();
};
X f(X);
void g()
{
X a(1);
X b = f(X(2));
a = f(b);
}
Zdes' nuzhen vremennyj ob容kt dlya postroeniya X(2), prezhde chem
peredat' ego funkcii f() s pomoshch'yu X(X&). Al'ternativnoe reshenie, -
postroit' ob容kt X(2) v pamyati, ispol'zuemoj dlya hraneniya parametra
pri pervom vyzove f(). Pomimo etogo, vremennyj ob容kt mozhet
ponadobit'sya dlya hraneniya rezul'tata f(X(2)) prezhde, chem kopirovat'
ego v ob容kt b s pomoshch'yu X(X&), i zdes' vozmozhno al'ternativnoe
reshenie: hranit' rezul'tat f(X(2)) v pamyati dlya ob容kta b. S drugoj
storony, sushchestvuet mnogo funkcij f(), dlya kotoryh vypolnenie
vyrazheniya a=f(a) trebuet vremennogo ob容kta ili dlya parametra a,
ili dlya rezul'tata f(a), chtoby izbezhat' nezhelatel'nogo ispol'zovaniya
pamyati, kotoroj pripisyvaetsya imya a.
Translyator obyazan garantirovat' unichtozhenie vremennyh ob容ktov.
Tochnyj moment unichtozheniya opredelyaetsya realizaciej. S vremennymi
ob容ktami mozhno proizvodit' tol'ko dve operacii: vybrat' znachenie
ob容kta (neyavno kopiruya ego) dlya ispol'zovaniya v drugom vyrazhenii,
ili vzyat' ssylku na nego. Esli znachenie vremennogo ob容kta polucheno,
on schitaetsya nenuzhnym i mozhet unichtozhat'sya nemedlenno. Esli na nego
poluchena ssylka, to unichtozhat' ego nel'zya, poka sushchestvuet ssylka.
Unichtozhenie dolzhno proizojti do vyhoda iz oblasti opredelennosti,
v kotoroj byl sozdan vremennyj ob容kt.
Drugoj vid vremennyh ob容ktov obsuzhdaetsya v $$R.8.4.3.
Preobrazovaniya ob容ktov klassa mozhno zadat' s pomoshch'yu konstruktorov
ili funkcij preobrazovaniya.
Takie preobrazovaniya, obychno nazyvaemye pol'zovatel'skimi,
ispol'zuyutsya neyavno v sovokupnosti so standartnymi preobrazovaniyami
($$R.4). Naprimer, funkciyu s formal'nym parametrom tipa X mozhno
vyzyvat' ne tol'ko s parametrom tipa X, no i parametrom tipa T,
esli sushchestvuet preobrazovanie tipa T v X. Pol'zovatel'skie
preobrazovaniya primenyayutsya v teh zhe situaciyah, chto i standartnye:
preobrazovanie inicializatorov ($$R.8.4), parametrov funkcii
($$R.5.2.2), vozvrashchaemyh funkciej znachenij ($$R.6.6.3, $$R.8.2.5),
vyrazhenij fakticheskih parametrov ($$R.5), vyrazhenij, upravlyayushchih
ciklom i vyborom operatorov ($$R.6.4,$$R.6.5) i yavnye operacii
preobrazovaniya tipa ($$R.5.2.3, $$R.5.4).
Pol'zovatel'skie preobrazovaniya primenyayutsya tol'ko v sluchae
ih odnoznachnosti ($$R.10.1.1, $$R.12.3.2). Preobrazovaniya prohodyat
proverku na sootvetstvie pravilam dostupa ($$R.11). Kak vsegda
proverka dostupa osushchestvlyaetsya posle razresheniya neodnoznachnosti
($$R.10.4).
Primenenie preobrazovanij pri vyzove funkcii rassmatrivaetsya na
primerah, privedennyh nizhe, a takzhe obsuzhdaetsya v $$R.13.2.
R.12.3.1 Preobrazovanie s pomoshch'yu konstruktora
Konstruktor, imeyushchij edinstvennyj parametr, zadaet preobrazovanie
tipa svoego fakticheskogo parametra v tip ego klassa, naprimer:
class X {
// ...
public:
X(int);
X(const char*, int = 0);
};
void f(X arg) {
X a = 1; // a = X(1);
X b = "Jessie"; // b = X("Jessie",0)
a = 2; // a = X(2)
f(3); // f(X(3))
}
Esli v klasse X net konstruktora, kotoryj dopuskaet zadannyj tip,
ne delaetsya popytki najti kakoj-libo konstruktor drugogo klassa ili
funkciyu preobrazovaniya dlya privedeniya zadannogo znacheniya v znachenie
tipa,dopustimogo dlya konstruktora klassa X, naprimer:
class X { /* ... */ X(int); };
class Y { /* ... */ Y(X); };
Y a = 1; // nedopustimo: preobrazovanie Y(X(1))
// ne primenyaetsya
R.12.3.2 Funkcii preobrazovaniya
Funkciya-chlen klassa X, imya kotoroj imeet vid,
imya-funkcii-preobrazovaniya:
operator imya-tipa-preobrazovaniya
imya-tipa-preobrazovaniya:
spisok-specifikacij-tipa opt operaciya-ptr opt
zadaet preobrazovanie iz tipa X v tip, opredelyaemyj konstrukciej
imya-tipa-preobrazovaniya. Takie funkcii-chleny nazyvayutsya funkciyami
preobrazovaniya. V konstrukcii spisok-specifikacij-tipa nel'zya
opisyvat' klassy, perechisleniya i imena-typedef, a takzhe nel'zya
zadavat' tipy formal'nyh parametrov i tip vozvrashchaemogo znacheniya.
Privedem primer:
class X {
// ...
public:
operator int();
};
void f(X a)
{
int i = int(a);
i = (int)a;
i = a;
}
Zdes' vo vseh treh operatorah prisvaivaemoe znachenie budet
preobrazovyvat'sya s pomoshch'yu funkcii X::operator int(). Pol'zovatel'skie
preobrazovaniya ne ogranichivayutsya tol'ko ispol'zovaniem v prisvaivanii
i inicializacii, naprimer:
void g(X a, X b)
{
int i = (a) ? 1+a : 0;
int j = (a&&b) ? a+b : i;
if (a) { // ...
}
}
Operacii preobrazovaniya nasleduyutsya. Funkcii preobrazovaniya
mogut byt' virtual'nymi.
K dannomu znacheniyu neyavno primenyaetsya ne bolee odnogo
pol'zovatel'skogo preobrazovaniya (s pomoshch'yu konstruktora ili funkcii
preobrazovaniya), naprimer:
class X {
// ...
public:
operator int();
};
class Y {
// ...
public:
operator X();
};
Y a;
int b = a; // nedopustimo: preobrazovanie
// a.operator X().operator int() ne primenyaetsya
int c = X(a); // normal'no: a.operator X().operator int()
Pol'zovatel'skie preobrazovaniya osushchestvlyayutsya neyavno tol'ko
pri uslovii ih odnoznachnosti. Funkciya preobrazovaniya proizvodnogo
klassa ne zakryvaet funkciyu preobrazovaniya bazovogo klassa, esli
tol'ko oni ne preobrazuyut k odnomu i tomu zhe tipu, naprimer:
class X {
public:
// ...
operator int();
};
class Y : public X {
public:
// ...
operator void*();
};
void f(Y& a)
{
if (a) { // oshibka: neodnoznachnost'
}
}
Destruktorom nazyvaetsya funkciya-chlen klassa cl s imenem ~cl, ona
ispol'zuetsya dlya unichtozheniya znachenij tipa cl neposredstvenno pered
unichtozheniem ob容kta, soderzhashchego ih. Destruktor ne imeet formal'nyh
parametrov i dlya nego nel'zya zadat' tip vozvrashchaemogo znacheniya
(dazhe void). Nel'zya primenyat' operaciyu vzyatiya adresa dlya destruktora.
Mozhno vyzyvat' destruktor dlya ob容ktov so specifikaciej const ili
volatile, no sam destruktor nel'zya opisyvat' s etimi specifikaciyami
($$R.9.3.1). Destruktor ne mozhet byt' i staticheskim.
Destruktory ne nasleduyutsya. Esli bazovyj klass ili chlen imeyut
destruktor, a sam proizvodnyj klass - net, to sozdaetsya standartnyj
destruktor, kotoryj vyzyvaet destruktory bazovyh klassov i chlenov
proizvodnogo klassa. Takie sozdannye destruktory imeyut specifikaciyu
public.
Telo destruktora vypolnyaetsya prezhde destruktorov dlya ob容ktov,
yavlyayushchihsya chlenami. Destruktory dlya nestaticheskih ob容ktov, yavlyayushchihsya
chlenami, vypolnyayutsya prezhde, chem destruktory dlya bazovyh klassov.
Destruktory dlya nevirtual'nyh bazovyh klassov vypolnyayutsya prezhde,
chem destruktory dlya virtual'nyh bazovyh klassov. Destruktory dlya
nevirtual'nyh bazovyh klassov vypolnyayutsya v poryadke, obratnom ih
opisaniyu v proizvodnom klasse. Destruktory virtual'nyh bazovyh
klassov vypolnyayutsya v poryadke, obratnom poyavleniyu ih pri obhode
snizu i sleva-napravo aciklichnogo napravlennogo grafa bazovyh
klassov. Zdes' "sleva-napravo" oznachaet poryadok poyavleniya imen
bazovyh klassov, kotoryj byl pri opisanii ih v proizvodnom klasse.
Destruktory dlya elementov massiva vyzyvayutsya v poryadke,
obratnom vyzovam pri ih postroenii.
Destruktor mozhet byt' virtual'nym.
V destruktore mozhno vyzyvat' funkciyu-chlen, sm. $$R.12.7.
Ob容kt klassa s destruktorom ne mozhet byt' chlenom ob容dineniya.
Destruktory vyzyvayutsya neyavno v sleduyushchih sluchayah:
(1) kogda ischezayut iz oblasti vidimosti ob容kty auto ($$R.3.5)
ili vremennye ob容kty ($$R.12.2, $$R.8.4.3);
(2) pri zavershenii programmy ($$R.3.4) dlya postroennyh staticheskih
ob容ktov ($$R.3.5);
(3) blagodarya obrashcheniyu k operacii delete ($$R.5.3.4) dlya ob容ktov,
sozdannyh s pomoshch'yu operacii new ($$R.5.3.3);
(4) pri yavnom vyzove.
Kogda destruktor vyzyvaetsya operaciej delete, to on osvobozhdaet
pamyat' dlya samogo bol'shego iz proizvodnyh klassov ($$R.12.6.2) togo
ob容kta, kotoryj ispol'zoval operaciyu delete() ($$R.5.3.4),
naprimer:
class X {
// ...
public:
X(int);
~X();
};
void g(X*);
void f() // obshchij sluchaj
{
X* p = new X(111); // razmeshchenie i inicializaciya
g(p);
delete p; // osvobozhdenie i udalenie
}
YAvnye vyzovy destruktorov primenyayutsya redko. Primerom etogo mozhet
sluzhit' vyzov destruktora dlya ob容ktov, sozdannyh v nekotoroj
opredelennoj adresnoj oblasti s pomoshch'yu operacii new. Razmeshchenie
ob容ktov v opredelennom adresnom prostranstve i posleduyushchee
unichtozhenie ih mozhet potrebovat'sya dlya ispol'zovaniya specificheskih
vozmozhnostej apparatury i dlya pravil'nogo funkcionirovaniya operativnoj
pamyati. Privedem primer:
void* operator new(size_t, void* p) { return p; }
void f(X* p);
static char buf[sizeof(X)];
void g() // redkij, special'nyj sluchaj
{
X* p = new(buf) X(222); // razmeshchenie v buf[] i inicializaciya
f(p);
p->X::~X(); // udalenie
}
Oboznacheniya, ispol'zovannye dlya yavnogo vyzova destruktora, mozhno
ispol'zovat' dlya imeni lyubogo prostogo tipa, naprimer,
int* p;
// ...
p->int::~int();
Ispol'zovanie takoj zapisi dlya tipa, u kotorogo net destruktora,
prohodit bessledno. Dopuskaya takuyu zapis', my razreshaem pol'zovatelyam
pisat' programmu, ne zadumyvayas' nad tem, est' li dannogo tipa
destruktor.
R.12.5 Svobodnaya pamyat'
Kogda sozdaetsya ob容kt s pomoshch'yu operacii new, dlya polucheniya svobodnoj
pamyati vyzyvaetsya (neyavno) funkciya operator new() ($$R.5.3.3).
Esli funkciya operator new() ne mozhet vypolnit' zapros, ona
vozvrashchaet 0.
V klasse X funkciya X::operator new() yavlyaetsya staticheskim chlenom,
dazhe esli ona ne opisana yavno kak static. Pervyj ee parametr dolzhen
imet' tip size_t, - zavisyashchij ot realizacii celochislennyj tip,
kotoryj opredelen v standartnom zagolovochnom fajle <stddef.h>, i
ona dolzhna vozvrashchat' znachenie tipa void*, naprimer:
class X {
// ...
void* operator new(size_t);
void* operator new(size_t, Arena*);
};
Pravila vybora podhodyashchej funkcii operator new() obsuzhdayutsya
v $$R.5.3.3.
V klasse X funkciya X::operator delete() yavlyaetsya staticheskim
chlenom, dazhe esli ona ne opisana yavno kak static. Pervyj ee parametr
dolzhen byt' tipa void* i mozhno dobavlyat' vtoroj parametr tipa
size_t. Ona ne mozhet vozvrashchat' kakoe-libo znachenie i tip
vozvrashchaemogo znacheniya dolzhen byt' void, naprimer:
class X {
// ...
void operator delete(void*);
};
class Y {
// ...
void operator delete(void*, size_t);
};
V kazhdom klasse mozhno opisat' tol'ko odnu funkciyu operator delete(),
znachit eta funkciya ne mozhet byt' peregruzhennoj. Global'naya funkciya
operator delete() imeet edinstvennyj parametr tipa void*.
Esli funkciya opisana s dvumya formal'nymi parametrami, ona vyzyvaetsya
s dvumya parametrami, vtoroj iz kotoryh pokazyvaet razmer udalyaemogo
ob容kta. Peredavaemyj razmer opredelyaetsya s pomoshch'yu destruktora
(esli on est') ili po tipu (staticheskomu) ukazatelya na udalyaemyj
ob容kt. Operaciya projdet korrektno, esli tip ukazatelya, zadannogo
kak fakticheskij parametr, budet sovpadat' s tipom ob容kta (a ne budet,
k primeru, prosto tipom ukazatelya na bazovyj klass) ili, esli
etot tip yavlyaetsya tipom ukazatelya na bazovyj klass s virtual'nym
destruktorom.
Dlya massivov ob容ktov tipa klass ispol'zuyutsya global'nye funkcii
operator new() i operator delete() ($$R.5.3.3, $$R.5.3.4).
Poskol'ku funkcii X::operator new() i X::operator delete()
staticheskie, oni ne mogut byt' virtual'nymi. Funkciya
operator delete(), kotoraya vyzyvaetsya iz destruktora dlya osvobozhdeniya
pamyati, vybiraetsya po obychnym pravilam oblastej vidimosti,
naprimer:
struct B {
virtual ~B();
void* operator new(size_t);
void operator delete(void*);
};
struct D : B {
~D();
void* operator new(size_t);
void operator delete(void*);
};
void f()
{
B* p = new D;
delete p;
}
V etom primere pamyat' dlya ob容kta klassa D vydelyaetsya s pomoshch'yu
D::operator new(), a blagodarya nalichiyu virtual'nogo destruktora,
osvobozhdaetsya s pomoshch'yu D::operator delete().
Ob容kt klassa bez konstruktorov, bez chastnyh ili zashchishchennyh chlenov,
bez virtual'nyh funkcij i bez bazovyh klassov mozhno inicializirovat'
s pomoshch'yu spiska inicializatorov ($$R.8.4.1). Ob容kt klassa s
konstruktorom dolzhen inicializirovat'sya ili imet' standartnyj
konstruktor ($$R.12.1). Standartnyj konstruktor ispol'zuetsya dlya
ob容ktov, kotorye ne prohodyat yavnoj inicializacii.
R.12.6.1 YAvnaya inicializaciya
Ob容kty klassov s konstruktorami ($$R.12.1) mozhno inicializirovat'
spiskom vyrazhenij, zaklyuchennym v skobki. |tot spisok schitaetsya
spiskom fakticheskih parametrov dlya vyzova konstruktora, proizvodyashchego
inicializaciyu. Inache, v kachestve inicializatora zadaetsya s pomoshch'yu
operacii = odno znachenie. Ono ispol'zuetsya kak fakticheskij parametr
dlya konstruktora kopirovaniya. Obychno mozhno obojtis' bez vyzova
konstruktora kopirovaniya, naprimer:
class complex {
// ...
public:
complex();
complex(double);
complex(double,double);
// ...
};
complex sqrt(complex,complex);
complex a(1); // inicializaciya vyzovom
// complex(double)
complex b = a; // inicializaciya kopirovaniem `a'
complex c = complex(1,2); // konstruktor complex(1,2)
// vyzyvaetsya complex(double,double)
// i kopiruetsya v `c'
complex d = sqrt(b,c); // vyzyvaetsya sqrt(complex,complex),
// rezul'tat kopiruetsya v `d'
complex e; // inicializaciya vyzovom konstruktora
complex f = 3; // complex(3), vyzyvaetsya
// complex(double) i rezul'tat
// kopiruetsya v `f'
Peregruzka operacii prisvaivaniya = ne okazyvaet vliyanie na
inicializaciyu.
Inicializaciya, proishodyashchaya pri peredache fakticheskih parametrov
i pri vozvrate iz funkcii, ekvivalentna inicializacii vida
T x = a;
Inicializaciya, proishodyashchaya v vyrazhenii operacii new ($$R.5.3.3) i
pri inicializacii bazovyh klassov i chlenov, ekvivalentna
inicializacii vida
T x(a);
Dlya massivov ob容ktov klassa s konstruktorami ispol'zuyutsya pri
inicializacii ($$R.12.1) konstruktory kak i dlya odinochnyh ob容ktov.
Esli okazalos', chto inicializatorov v spiske men'she, chem elementov
massiva, ispol'zuetsya standartnyj konstruktor ($$R.12.1). Esli ego
net, spisok inicializatorov dolzhen byt' polnym. Privedem primer:
complex cc = { 1, 2 }; // oshibka: neobhodimo
// ispol'zovat' konstruktor
complex v[6] = { 1,complex(1,2),complex(),2 };
Zdes' v[0] i v[3] inicializiruyutsya znacheniem complex::complex(double),
v[1] inicializiruetsya complex::complex(double,double), a v[2],
v[4] i v[5] inicializirovany complex::complex().
Ob容kt klassa M moet byt' chlenom klassa X v odnom iz sleduyushchih
sluchaev:
(1) M ne imeet konstruktora;
(2) M imeet standartnyj konstruktor;
(3) X imeet konstruktor i kazhdyj iz nih zadaet inicializator-ctor
($$R.12.6.2) dlya chlena M.
V sluchae 2 pri sozdanii sostavnogo ob容kta vyzyvaetsya standartnyj
konstruktor. Esli chlen sostavnogo ob容kta imeet destruktor, to on
vyzyvaetsya pri unichtozhenii sostavnogo ob容kta.
Konstruktory dlya nelokal'nyh staticheskih ob容ktov vyzyvayutsya v
tom poryadke, v kakom oni idut v tekste programmy, destruktory
vyzyvayutsya v obratnom poryadke, sm. takzhe $$R.3.4, $$R.6.7,
$$R.9.4.
R.12.6.2 Inicializaciya chlenov i bazovyh klassov
V opredelenii konstruktora mozhno zadat' inicializaciyu pryamyh
bazovyh klassov i chlenov, ne nasleduemyh iz bazovyh klassov. |to
osobenno polezno dlya teh ob容ktov, konstant i ssylok, dlya kotoryh
razlichayutsya semantiki prisvaivaniya i inicializacii. Konstrukciya
inicializator-ctor imeet vid
inicializator-ctor:
: spisok-inicializatorov-chlenov
spisok-inicializatorov-chlenov:
inicializator-chlena
inicializator-chlena , spisok-inicializatorov-chlena
inicializator-chlena:
polnoe-imya-klassa ( spisok-vyrazhenij opt )
identifikator
Spisok parametrov ispol'zuetsya dlya inicializacii nestaticheskih chlenov
ili ob容ktov bazovogo klassa. |to edinstvennyj sposob inicializacii
nestaticheskih chlenov, yavlyayushchihsya ssylkami ili ob容ktami tipa const,
naprimer:
struct B1 { B1(int); /* ... */ };
struct B2 { B2(int); /* ... */ };
struct D : B1, B2 {
D(int);
B1 b;
const c;
};
D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4)
{ /* ... */ }
D d(10);
V nachale inicializiruyutsya bazovye klassy v poryadke ih opisaniya
(nezavisimo ot poryadka inicializatorov-chlenov), zatem po toj zhe
sheme inicializiruyutsya chleny, i nakonec vypolnyaetsya telo D::D()
($$R.12.1). Poryadok opisaniya vyderzhivaetsya dlya togo, chtoby garantirovat',
chto vlozhennye ob容kty i chleny budut unichtozhat'sya v poryadke, obratnom
ih inicializacii.
Osobyj sluchaj predstavlyayut virtual'nye bazovye klassy. Oni sozdayutsya
prezhde, chem lyuboj nevirtual'nyj bazovyj klass i v tom zhe poryadke,
v kakom poyavlyayutsya pri obhode snizu i sleva-napravo aciklichnogo
napravlennogo grafa bazovyh klassov. Poryadok "sleva-napravo" - eto
tot, v kotorom imena bazovyh klassov zadayutsya pri opisanii v
proizvodnom klasse.
Polnym nazyvaetsya ob容kt, kotoryj ne yavlyaetsya vlozhennym ob容ktom,
predstavlyayushchim nekotoryj bazovyj klass. Klass takogo ob容kta
nazyvayut naibol'shim proizvodnym klassom ob容kta. Vse vlozhennye
ob容kty virtual'nyh bazovyh klassov inicializiruyutsya s pomoshch'yu
konstruktora naibol'shego proizvodnogo klassa. Esli v konstruktore
naibol'shego proizvodnogo klassa ne zadan inicializator-chlena dlya
virtual'nogo bazovogo klassa, togda etot virtual'nyj bazovyj klass
dolzhen imet' standartnyj konstruktor,libo ne imet' nikakogo
konstruktora. Vsyakij inicializator-chlena dlya virtual'nogo bazovogo
klassa, zadannyj ne v konstruktore klassa polnogo ob容kta, ignoriruetsya.
Privedem primer:
class V {
public:
V();
V(int);
// ...
};
class A : public virtual V {
public:
A();
A(int);
// ...
};
class B : public virtual V {
public:
B();
B(int);
// ...
};
class C : public A, public B, private virtual V {
public:
C();
C(int);
// ...
};
A::A(int i) : V(i) { /* ... */ }
B::B(int i) { /* ... */ }
C::C(int i) { /* ... */ }
V v(1); // use V(int)
A a(2); // use V(int)
B b(3); // use V()
C c(4); // use V()
Inicializator-chlena vychislyaetsya v oblasti vidimosti konstruktora,
v kotorom on poyavilsya. Naprimer, v sleduyushchem fragmente
class X {
int a;
public:
const int& r;
X()::r(a) { }
};
X::r inicializiruetsya dlya kazhdogo ob容kta klassa X ssylkoj na X::a.
R.12.7 Konstruktory i destruktory
V konstruktorah i destruktorah mozhno vyzyvat' funkciyu-chlen. Otsyuda
sleduet, chto mozhno vyzyvat' (neposredstvenno ili kosvenno)
virtual'nye funkcii. Vyzyvaemaya funkciya dolzhna byt' opredelena
v klasse samogo konstruktora ili destruktora ili v bazovyh klassah,
no ne dolzhna byt' funkciej, kotoraya ih podavlyaet v proizvodnom klasse.
|tim obespechivaetsya to, chto eshche nesozdannye ob容kty ne budut
ispol'zovany pri vypolnenii konstruktora ili destruktora. Rassmotrim
primer:
class X {
public:
virtual void f();
X() { f(); } // vyzov X::f()
~X() { f(); } // vyzov X::f()
};
class Y : public X {
int& r;
public:
void f()
{
r++; // beda, esli `r' ne inicializirovano
}
Y(int& rr) ::r(rr) { }
};
Rezul'tat neposredstvennogo ili kosvennogo vyzova iz konstruktora
chistoj virtual'noj funkcii dlya inicializiruemogo ob容kta neopredelen,
esli tol'ko yavno ne ispol'zovano utochnenie imeni funkcii ($$R.10.3).
R.12.8 Kopirovanie ob容ktov klassa
Ob容kty klassa mogut kopirovat'sya dvumya sposobami: libo prisvaivaniem
($$R.5.17), libo inicializaciej ($$R.12.1, $$R.8.4), kotoraya mozhet
proishodit' pri peredache parametrov ($$R.5.2.2) ili
rezul'tata funkcii ($$R.6.6.3). Dlya klassa X eti dve operacii
konceptual'no realizuyutsya kak operaciya prisvaivaniya i konstruktor
kopirovaniya ($$R.12.1). V programme mozhno opredelit' ili odnu iz nih,
ili obe. Esli pol'zovatel' ne opredelil ih v programme, to oni budut
dlya vseh chlenov klassa X opredelyat'sya sootvetstvenno kak prisvaivanie
po chlenam i inicializaciya po chlenam.
Esli vse bazovye klassy i vse chleny klassa X imeyut konstruktor
kopirovaniya, v kotorom dopustimy v kachestve parametra ob容kty tipa
const, to porozhdaemyj konstruktor kopirovaniya dlya X budet imet'
edinstvennyj parametr tipa const X& i zapisyvat'sya tak:
X::X(const X&)
Inache, u nego budet edinstvennyj parametr tipa X&:
X::X(X&)
i inicializaciya kopirovaniem ob容ktov tipa const klassa X budet
nevozmozhna.
Analogichno, esli vse bazovye klassy i chleny klassa X imeyut
operaciyu prisvaivaniya, dopuskayushchuyu parametry tipa const, togda
porozhdaemaya dlya X operaciya prisvaivaniya budet imet' edinstvennyj
parametr tipa const X& i zapisyvat'sya tak:
X& X::operator=(const X&)
Inache, u nee budet edinstvennyj parametr tipa X&:
X& X::operator=(X&)
i prisvaivanie kopirovaniem ob容ktov klassa X tipa const budet
nevozmozhno. Standartnaya operaciya prisvaivaniya vozvrashchaet ssylku
na ob容kt, kotoryj nuzhno bylo kopirovat'.
Ob容kty, predstavlyayushchie virtual'nye bazovye klassy, budut
inicializirovat'sya tol'ko odin raz s pomoshch'yu porozhdaemogo
konstruktora kopirovaniya. Ob容kty, predstavlyayushchie virtual'nye
bazovye klassy, dopuskayut prisvaivaniya im tol'ko odin raz s pomoshch'yu
porozhdaemoj operacii prisvaivaniya.
Prisvaivanie po chlenam i inicializaciya po chlenam oznachayut
sleduyushchee: esli klass X imeet v kachestve chlena klass M, dlya realizacii
prisvaivaniya i inicializacii chlena ispol'zuyutsya operacii prisvaivaniya
v M i konstruktor kopirovaniya M sootvetstvenno. Esli klass imeet
chlen tipa const, ili chlen, yavlyayushchijsya ssylkoj, ili chlen ili bazovyj
klass takogo klassa, gde funkciya operator=() yavlyaetsya chastnoj,
to dlya nego standartnaya operaciya prisvaivaniya ne mozhet byt' sozdana.
Analogichno, esli chlen ili bazovyj klass klassa M imeet chastnyj
konstruktor kopirovaniya, to standartnyj konstruktor kopirovaniya dlya
takogo klassa ne mozhet byt' sozdan.
Poka ne poyavitsya neobhodimost' v opredelenii, standartnye prisvaivanie
i konstruktor kopirovaniya budut tol'ko opisany (t.e. ne budet sozdano
telo funkcii). Inymi slovami, funkciya X::operator=() budet porozhdena
tol'ko togda, kogda net yavnogo opisaniya operacij prisvaivaniya, a ob容kt
klassa X prisvaivaetsya ob容ktu klassa X ili ob容ktu klassa, proizvodnogo
ot X, ili vychislyaetsya adres funkcii X::operator=(). Analogichnaya situaciya
s inicializaciej.
Esli prisvaivanie i konstruktor kopirovaniya opisany neyavno, to
oni budut obshchimi funkciyami-chlenami i operaciya prisvaivaniya dlya klassa
X opredelyaetsya takim obrazom, chto ee rezul'tatom yavlyaetsya ssylka
tipa X& na ob容kt, kotoromu prisvaivayut.
Esli v klasse X est' funkciya X::operator=(), parametrom kotoroj
yavlyaetsya sam klass X, to standartnoe prisvaivanie ne budet
porozhdat'sya. Esli v klasse opredelen kakoj-libo konstruktor
kopirovaniya, to standartnyj konstruktor kopirovaniya ne budet
porozhdat'sya. Privedem primer:
class X {
// ...
public:
X(int);
X(const X&, int = 1);
};
X a(1); // vyzov X(int)
X b(a,0); // vyzov X(const X&,int)
X c = b; // vyzov X(const X&,int)
Prisvaivanie ob容ktov klassa X opredelyaetsya cherez funkciyu
X::operator=(const X&). |to oznachaet ($$R.12.3), chto ob容kty
proizvodnogo klassa mozhno prisvaivat' ob容ktam obshchego bazovogo
klassa, naprimer:
class X {
public:
int b;
};
class Y : public X {
public:
int c;
};
void f()
{
X x1;
Y y1;
x1 = y1; // normal'no
y1 = x1; // oshibka
}
V etom primere y1.b prisvaivaetsya x1.b, a x1.c ne kopiruetsya.
Kopirovanie odnogo ob容kta v drugoj s pomoshch'yu standartnoj
operacii kopirovaniya ili standartnogo konstruktora kopirovaniya
ne izmenyaet strukturu oboih ob容ktov. Privedem primer:
struct s {
virtual f();
// ...
};
struct ss : public s {
f();
// ...
};
void f()
{
s a;
ss b;
a = b; // na samom dele vypolnyaetsya a.s::operator=(b)
b = a; // oshibka
a.f(); // vyzov s::f
b.f(); // vyzov ss::f
(s&)b = a; // prisvaivanie a b
// na samom dele vypolnyaetsya ((s&)b).s::operator=(a)
b.f(); // vse eshche vyzov ss::f
}
Vyzov a.f() privedet k vyzovu s::f() (kak i dolzhno byt' dlya ob容kta
klassa s ($$R.10.2)), a vyzov b.f() privedet k vyzovu ss::f()
( kak i dolzhno byt' dlya ob容kta klassa ss).
Govoryat, chto imya peregruzheno, esli dlya nego zadano neskol'ko razlichnyh
opisanij funkcij v odnoj oblasti vidimosti. Pri ispol'zovanii imeni
vybor pravil'noj funkcii proizvoditsya putem sopostavleniya tipov
formal'nyh parametrov s tipami fakticheskih parametrov, naprimer:
double abs(double);
int abs(int);
abs(1); // vyzov abs(int)
abs(1.0); // vyzov abs(double)
Poskol'ku pri lyubom tipe T i dlya samogo T , dlya i T& dopustimo odno i
to zhe mnozhestvo inicializiruyushchih znachenij, funkcii, tipy parametrov
kotoryh razlichayutsya tol'ko ispol'zovaniem, ili ne ispol'zovaniem
ssylki, ne mogut imet' odinakovye imena, naprimer:
int f(int i)
{
// ...
}
int f(int& r) // oshibka: tipy funkcij
{ // nedostatochno razlichny
// ...
}
Analogichno, poskol'ku dlya lyubom tipe T dlya samogo T, const T i
volatile T dopustimo odno i to zhe mnozhestvo inicializiruyushchih
znachenij, funkcii, tipy parametrov kotoryh otlichayutsya tol'ko
ukazannoj specifikaciej, ne mogut imet' odinakovye imena. Odnako,
razlichit' const T&, volatile T& i prosto T& mozhno, poetomu dopustimy
opredeleniya funkcij s odnim imenem, kotorye razlichayutsya tol'ko
v ukazannom otnoshenii. Analogichno, dopustimy opredeleniya funkcij
s odnim imenem, tipy parametrov kotoryh razlichayutsya tol'ko kak
tipy vida const T*, volatile T* i prosto T*.
Ne mogut imet' odinakovye imena funkcii, kotorye otlichayutsya
tol'ko tipom vozvrashchaemogo znacheniya.
Ne mogut imet' odinakovye imena funkcii-chleny, odna iz kotoryh
staticheskaya, a drugaya net ($$R.9.4).
S pomoshch'yu konstrukcii typedef ne sozdayutsya novye tipy,
a tol'ko opredelyaetsya sinonim tipa ($$R.7.1.3), poetomu funkcii,
kotorye otlichayutsya tol'ko za schet ispol'zovaniya tipov, opredelennyh s
pomoshch'yu typedef, ne mogut imet' odinakovye imena. Privedem
primer:
typedef int Int;
void f(int i) { /* ... */ }
void f(Int i) { /* ... */ } // oshibka: pereopredelenie f
S drugoj storony vse perechisleniya schitayutsya raznymi tipami, i s ih
pomoshch'yu mozhno razlichit' peregruzhennye funkcii, naprimer:
enum E { a };
void f(int i) { /* ... */ }
void f(E i) { /* ... */ }
Tipy parametrov, kotorye razlichayutsya tol'ko tem, chto v odnom
ispol'zuetsya ukazatel' *, a v drugom massiv [], schitayutsya identichnymi.
Napomnim, chto dlya tipa parametra vazhny tol'ko vtoroj i posleduyushchie
indeksy mnogomernogo massiva ($$R.8.2.4). Podtverdim skazannoe
primerom:
f(char*);
f(char[]); // identichno f(char*);
f(char[7]); // identichno f(char*);
f(char[9]); // identichno f(char*);
g(char(*)[10]);
g(char[5][10]); // identichno g(char(*)[10]);
g(char[7][10]); // identichno g(char(*)[10]);
g(char(*)[20]); // otlichno ot g(char(*)[10]);
R.13.1 Sopostavlenie opisanij
Dva opisaniya funkcij s odinakovymi imenami otnosyatsya k odnoj i toj
zhe funkcii, esli oni nahodyatsya v odnoj oblasti vidimosti i imeyut
identichnye tipy parametrov ($$R.13). Funkciya-chlen proizvodnogo
klassa otnositsya k inoj oblasti vidimosti, chem funkciya-chlen
bazovogo klassa s tem zhe imenem. Rassmotrim primer:
class B {
public:
int f(int);
};
class D : public B {
public:
int f(char*);
};
Zdes' D::f(char*) skoree skryvaet B::f(int), chem peregruzhaet etu
funkciyu.
void h(D* pd)
{
pd->f(1); // oshibka: D::f(char*) skryvaet B::f(int)
pd->B::f(1); // normal'no
pd->f("Ben"); // normal'no, vyzov D::f
}
Funkciya, opisannaya lokal'no, nahoditsya v inoj oblasti vidimosti, chem
funkciya s fajlovoj oblast'yu vidimosti.
int f(char*);
void g()
{
extern f(int);
f("asdf"); // oshibka: f(int) skryvaet f(char*) poetomu
// v tekushchej oblasti vidimosti net f(char*)
}
Dlya raznyh variantov peregruzhennoj funkcii-chlena mozhno zadat'
raznye pravila dostupa, naprimer:
class buffer {
private:
char* p;
int size;
protected:
buffer(int s, char* store) { size = s; p = store; }
// ...
public:
buffer(int s) { p = new char[size = s]; }
};
R.13.2 Sopostavlenie parametrov
Pri vyzove funkcii s dannym imenem proishodit vybor iz vseh
funkcij s etim imenem, kotorye nahodyatsya v tekushchej oblasti vidimosti, i
dlya kotoryh sushchestvuyut preobrazovaniya tipa, delayushchie vyzov vozmozhnym.
Vybiraetsya ta funkciya, kotoraya naibolee sootvetstvuet fakticheskim
parametram. Ona nahoditsya v oblasti peresecheniya mnozhestv
funkcij, kazhdoe iz kotoryh naibolee sootvetstvuyut vyzovu po dannomu
fakticheskomu parametru. Operaciya vyzova schitaetsya dopustimoj, esli v etom
peresechenii nahoditsya tol'ko odin chlen. Funkciya, vybrannaya takim obrazom,
dolzhna bolee lyuboj drugoj funkcii s tem zhe imenem sootvetstvovat'
vyzovu, hotya by po odnomu iz parametrov (neobyazatel'no eto
budet odin i tot zhe parametr dlya raznyh funkcij). V protivnom sluchae,
vyzov schitaetsya nedopustimym.
Pri sopostavlenii parametrov rassmatrivayut funkciyu s chislom
standartnyh znachenij parametrov ($$R.8.2.6), ravnym n, kak
n+1 funkcij s razlichnym chislom parametrov.
Pri sopostavlenii parametrov nestaticheskuyu funkciyu-chlen
rassmatrivayut kak funkciyu, imeyushchuyu dopolnitel'nyj parametr,
ukazyvayushchij na ob容kt, dlya kotorogo vyzyvaetsya funkciya. |tot
dopolnitel'nyj formal'nyj parametr dolzhen sopostavlyat'sya ili
s ob容ktom, ili s ukazatelem na ob容kt, zadannymi v yavnoj operacii
vyzova funkcii-chlena ($$R.5.2.4), ili zhe s pervym operandom
peregruzhennoj funkcii operator ($$R.13.4). Dlya etogo dopolnitel'nogo
parametra ne ispol'zuetsya nikakih vremennyh ob容ktov, a dlya dostizheniya
sopostavleniya ne proizvoditsya nikakih pol'zovatel'skih preobrazovanij
tipa.
Esli yavno vyzyvaetsya chlen klassa X, ispol'zuya ukazatel' i operaciyu
->, to schitaetsya, chto dopolnitel'nyj parametr imeet tip const* X dlya
chlenov tipa const, volatile* X dlya chlenov tipa volatile i
X* dlya vseh ostal'nyh chlenov. Esli yavno vyzyvaetsya funkciya-chlen,
ispol'zuya ob容kt i operaciyu ., a takzhe, esli vyzyvaetsya funkciya
dlya pervogo operanda peregruzhennoj funkcii operator ($$R.9.4),
to schitaetsya, chto dopolnitel'nyj parametr imeet tip: const X& dlya
chlenov tipa const, volatile X& dlya chlenov tipa volatile i X&
dlya vseh ostal'nyh chlenov. Pervyj operand dlya ->* i .* rassmatrivaetsya
tak zhe, kak i pervyj operand dlya -> i . sootvetstvenno.
|llipsis v spiske formal'nyh parametrov ($$R.8.2.5) mozhet
sopostavlyat'sya s fakticheskim parametrom lyubogo tipa.
Dlya dannogo fakticheskogo parametra dopuskaetsya tol'ko takaya
posledovatel'nost' preobrazovanij tipa, kotoraya soderzhit ne bolee
odnogo pol'zovatel'skogo preobrazovaniya. Ee nel'zya sokratit',
isklyuchiv odno ili neskol'ko preobrazovanij, do posledovatel'nosti,
kotoraya takzhe privodit k tipu, sopostavimomu s tipom rassmatrivaemogo
formal'nogo parametra. Takaya posledovatel'nost' preobrazovanij
nazyvaetsya naibolee sootvetstvuyushchej posledovatel'nost'yu.
Naprimer, posledovatel'nost' int->float->double zadaet
preobrazovanie int v double, no ee nel'zya nazvat' naibolee
sootvetstvuyushchej posledovatel'nost'yu, poskol'ku v nej soderzhitsya
bolee korotkaya posledovatel'nost' int->double.
Krome opisannyh nizhe sluchaev, sleduyushchie trivial'nye
preobrazovaniya tipa T ne vliyayut na svojstvo posledovatel'nosti
byt' naibolee sootvetstvuyushchej:
ishodnyj tip tip rezul'tata
T T&
T& T
T[] T*
T(parametry) T(*)(parametry)
T const T
T volatile T
T* const T*
T* volatile T*
Posledovatel'nosti trivial'nyh preobrazovanij, kotorye otlichayutsya
tol'ko poryadkom preobrazovanij, schitayutsya sovpadayushchimi. Otmetim,
chto dlya funkcij s formal'nym parametrom tipa T, const T, volatile T,
T&, const T& i volatile T& dopustim fakticheskij parametr iz odno i
togo zhe mnozhestva znachenij. Pri neobhodimosti dlya razdeleniya
posledovatel'nostej preobrazovanij ispol'zuyutsya specifikacii const i
volatile, kak opisano v pravile [1] nizhe.
Dlya formal'nogo parametra tipa T& trebuetsya vremennaya peremennaya
v sluchayah, esli: fakticheskij parametr ne yavlyaetsya adresom, ili imeet tip,
otlichnyj ot T, v tom chisle tip volatile. Nalichie takoj peremennoj
ne vliyaet na sopostavlenie parametrov. Odnako, ono mozhet povliyat'
na dopustimost' rezul'tata sopostavleniya, t.k. vremennuyu peremennuyu
nel'zya ispol'zovat' dlya inicializacii ssylok, ne yavlyayushchihsya
const ($$R.8.4.3).
Posledovatel'nosti preobrazovanij rassmatrivayutsya soglasno
sleduyushchim pravilam:
[1] Tochnoe sopostavlenie. Posledovatel'nosti iz nulya ili bolee
trivial'nyh preobrazovanij predpochtitel'nee lyubyh drugih
posledovatel'nostej. Iz bolee slozhnyh posledovatel'nostej
naibolee predpochtitel'ny te, v kotoryh net preobrazovanij
T* v const T*, T* v volatile T*, T& v const T& ili
T& v volatile T&.
[2] Sopostavlenie so standartnymi preobrazovaniyami osnovnyh tipov.
Iz posledovatel'nostej, ne otnosyashchihsya k [1], naibolee
predpochtitel'ny te, kotorye soderzhat tol'ko standartnye
celochislennye preobrazovaniya ($$R.4.1),
preobrazovaniya float v double i trivial'nye preobrazovaniya.
[3] Sopostavlenie s lyubymi standartnymi preobrazovaniyami.
iz posledovatel'nostej, ne otnosyashchihsya k [2], naibolee
predpochtitel'ny te, kotorye soderzhat tol'ko lyubye
standartnye preobrazovaniya ($$R.4.1, $$R.4.2, $$R.4.3, $$R.4.4,
$$R.4.5, $$R.4.6, $$R.4.7, $$R.4.8) i trivial'nye
preobrazovaniya. Dlya etih posledovatel'nostej esli A yavlyaetsya
pryamym ili kosvennym obshchim bazovym dlya klassa B,
to preobrazovanie B* v A* predpochtitel'nee preobrazovaniya B*
v void* ili const void*. Dalee, esli B yavlyaetsya pryamym ili
kosvennym bazovym klassom dlya C, to predpochtitel'nee preobrazovanie
C* v B*, chem C* v A*, i predpochtitel'nee preobrazovanie C& v B&,
chem C& v A&. Ierarhiya klassov vystupaet zdes' kriterij otbora
preobrazovanij ukazatelya v chlen ($$R.4.8).
[4] Sopostavlenie s pol'zovatel'skimi preobrazovaniyami.
Iz posledovatel'nostej, ne otnosyashchihsya k [3], naibolee
predpochtitel'ny te, kotorye soderzhat tol'ko
pol'zovatel'skie ($$R.12.3), standartnye ($$R.4) i trivial'nye
preobrazovaniya.
[5] Sopostavlenie s ellipsisom.
Posledovatel'nosti, kotorye trebuyut sopostavleniya s ellipsisom,
schitayutsya naimenee predpochtitel'nymi.
Pol'zovatel'skie preobrazovaniya vybirayut, ishodya iz tipa
peremennoj, kotoraya inicializiruetsya ili kotoroj prisvaivaetsya
znachenie.
class Y {
// ...
public:
operator int();
operator double();
};
void f(Y y)
{
int i = y; // vyzov Y::operator int()
double d;
d = y; // vyzov Y::operator double()
float f = y; // oshibka: neodnoznachnost'
}
Standartnye preobrazovaniya ($$R.4) mogut primenyat'sya k parametru,
kak do pol'zovatel'skogo preobrazovaniya, tak i posle nego.
struct S { S(long); operator int(); };
void f(long), f(char*);
void g(S), g(char*);
void h(const S&), h(char*);
void k(S& a)
{
f(a); // f(long(a.operator int()))
g(1); // g(S(long(1)))
h(1); // h(S(long(1)))
}
Esli dlya parametra trebuetsya pol'zovatel'skoe preobrazovanie, to ne
uchityvayutsya nikakie standartnye preobrazovaniya, kotorye mogut
zatragivat' etot parametr, naprimer:
class x {
public:
x(int);
};
class y {
public:
y(long);
};
void f(x);
void f(y);
void g()
{
f(1); // neodnoznachnost'
}
Zdes' vyzov f(1) neodnoznachen. Nesmotrya na to, chto dlya vyzova
f(y(long(1))) trebuetsya na odno standartnoe preobrazovanie bol'she,
chem dlya vyzova f(x(1)), vtoroj vyzov ne yavlyaetsya predpochtitel'nym.
Preobrazovaniya s pomoshch'yu konstruktora ($$R.12.1) i s pomoshch'yu
funkcii preobrazovaniya ($$R.12.3.2) ravnopravny.
struct X {
operator int();
};
struct Y {
Y(X);
};
Y operator+(Y,Y);
void f(X a, X b)
{
a+b; // oshibka, neodnoznachnost':
// operator+(Y(a), Y(b)) ili
// a.operator int() + b.operator int()
}
R.13.3 Adres peregruzhennoj funkcii
Kogda funkciya s nekotorym imenem ispol'zuetsya bez parametrov, sredi
vseh funkcij s takim imenem v tekushchej oblasti vidimosti vybiraetsya
edinstvennaya, kotoraya tochno sootvetstvuet naznacheniyu. Naznacheniem
mozhet byt':
inicializiruemyj ob容kt ($$R.8.4);
levaya chast' operacii prisvaivaniya ($$R.5.17);
formal'nyj parametr funkcii ($$R.5.2.2);
formal'nyj parametr pol'zovatel'skoj operacii ($$R.13.4);
tip znacheniya, vozvrashchaemogo funkciej ($$R.8.2.5).
Otmetim, chto esli f() i g() yavlyayutsya peregruzhennymi funkciyami, to
dlya pravil'noj interpretacii f(&g) ili ekvivalentnogo vyrazheniya
f(g) nuzhno rassmotret' peresechenie mnozhestv vybora dlya f() i g().
Privedem primer:
int f(double);
int f(int);
int (*pfd)(double) = &f;
int (*pfi)(int) = &f;
int (*pfe)(...) = &f; // oshibka: nesootvetstvie tipov
Poslednyaya inicializaciya oshibochna, ne iz-za neodnoznachnosti, a
potomu, chto ne opredeleno ni odnoj funkcii f() tipa int(...).
Otmetim, chto ne sushchestvuet nikakogo standartnogo preobrazovaniya
($$R.4) ukazatelya na funkciyu odnogo tipa v ukazatel' na funkciyu
drugogo tipa ($$R.4.6). V chastnosti, dazhe esli B yavlyaetsya obshchim
bazovym klassom D, dve sleduyushchie inicializacii nedopustimy:
D* f();
B* (*p1)() = &f; // oshibka
void g(D*);
void (*p2)(B*) = &g; // oshibka
R.13.4 Peregruzhennye operacii
Peregruzhat' mozhno bol'shinstvo operacij.
imya-funkcii-operator:
operator operaciya
operaciya: odin iz
new delete
+ - * / % ^ & | ~
! = < > += -= *= /= %=
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- , ->* ->
() []
Dve poslednie operacii - eto vyzov funkcii ($$R.5.2.2) i indeksaciya
($$R.5.2.1).
Mozhno peregruzhat' sleduyushchie (kak binarnye, tak i unarnye)
operacii:
+ - * &
Nel'zya peregruzhat' sleduyushchie operacii:
. .* :: ?: sizeof
a takzhe i special'nye simvoly preprocessora # i ## ($$R.16).
Obychno funkcii, zadayushchie operacii (funkciya-operator) ne vyzyvayutsya
yavno, k nim obrashchayutsya dlya vypolneniya operacij ($$R.13.4.1, $$R.13.4.2).
Odnako, k nim mozhno obrashchat'sya yavno, naprimer:
complex z = a.operator+(b); // complex z = a+b
void* p = operator new(sizeof(int)*n);
Operacii new i delete opisany v $$R.5.3.3 i $$R.5.3.4 i k nim
ne otnosyatsya perechislyaemye nizhe pravila.
Funkciya-operator mozhet byt' funkciej-chlenom ili imet' po krajnej
mere odin parametr tipa klass ili ssylka na klass. Nel'zya izmenit'
prioritet, poryadok vypolneniya ili chislo operandov operacii, no
mozhno izmenit' predopredelennoe naznachenie takih operacij: =,
unarnaya & i ,(zapyatoj), esli oni primenyayutsya k ob容ktu tipa klass.
Za isklyucheniem funkcii operator=(), funkciya-operator nasleduetsya.
Pravila dlya operator=() dany v $$R.12.8.
|kvivalentnost' nekotoryh operacij nad osnovnymi tipami
(naprimer, ++a ekvivalentno a+=1) mozhet ne sohranyat'sya dlya takih
zhe operacij nad klassami. Dlya nekotoryh operacij trebuetsya, chtoby
v sluchae ispol'zovaniya osnovnyh tipov operand byl adresom (naprimer,
dlya +=). |to trebovanie mozhet byt' snyato, esli operaciya zadana nad
klassami.
Peregruzhennaya operaciya ne mozhet imet' standartnye znacheniya
parametrov ($$R.8.2.6).
Operacii, kotorye yavno ne ukazany v $$R.13.4.3-$$R.13.4.7,
dejstvuyut kak obychnye unarnye ili binarnye operacii, podchinyayushchiesya
pravilam, privedennym v $$R.13.4.1 ili $$R.13.4.2.
R.13.4.1 Unarnye operacii
Prefiksnuyu unarnuyu operaciyu mozhno zadat' s pomoshch'yu nestaticheskoj
funkcii-chlena ($$R.9.3), bez parametrov ili s pomoshch'yu
funkcii, ne yavlyayushchejsya chlenom, s odnim parametrom. Takim obrazom,
dlya vsyakoj prefiksnoj unarnoj operacii @, vyrazhenie @x mozhet
interpretirovat'sya kak x.operator@() ili kak operator@(x).
Esli opisany funkcii-operatory oboih vidov, to kakaya iz nih budet
ispol'zovat'sya pri vyzove, opredelyaetsya pravilami sopostavleniya
parametrov ($$R.13.2). Postfiksnye unarnye operacii, takie kak ++ i -- ,
ob座asnyayutsya v $$R.13.4.7.
R.13.4.2 Binarnye operacii
Binarnuyu operaciyu mozhno zadat' s pomoshch'yu nestaticheskoj
funkcii-chlena ($$R.9.3), imeyushchej odin parametr, ili s pomoshch'yu
funkcii, ne yavlyayushchejsya chlenom, s dvumya parametrami. Takim obrazom,
dlya vsyakoj binarnoj operacii @ vyrazhenie x@y mozhet interpretirovat'sya
kak x.operator@(y) ili kak operator@(x,y). Esli opisany
funkcii-operatory oboih vidov, to kakaya iz nih budet ispol'zovat'sya
pri vyzove, opredelyaetsya pravilami sopostavleniya parametrov ($$R.13.2).
Funkciya prisvaivaniya operator=() dolzhna byt' nestaticheskoj
funkciej-chlenom. Ona ne nasleduetsya ($$R.12.8). Bolee togo, esli
pol'zovatel' ne opredelil dlya klassa X funkciyu operator=, to
ispol'zuetsya standartnaya funkciya operator=, kotoraya opredelyaetsya
kak prisvaivanie po chlenam dlya klassa X.
X& X::operator=(const X& from)
{
// kopirovanie po chlenam X
}
Vyzov funkcii est' konstrukciya vida:
pervichnoe-vyrazhenie ( spisok-vyrazhenij opt )
Ona schitaetsya binarnoj operaciej, v kotoroj pervichnoe-vyrazhenie
predstavlyaet pervyj operand, a spisok-vyrazhenij (vozmozhno pustoj),
- vtoroj operand. Imenem, zadayushchim funkciyu, sluzhit operator(), i vyzov
x(arg1,arg2,arg3) dlya ob容kta klassa x interpretiruetsya kak
x.operator()(arg1,arg2,arg3). Funkciya operator() dolzhna byt'
nestaticheskoj funkciej-chlenom klassa x.
Indeksaciya, opredelyaemaya kak:
pervichnoe-vyrazhenie [ vyrazhenie ]
schitaetsya binarnoj operaciej. Vyrazhenie s indeksaciej x[y] dlya ob容kta
klassa x interpretiruetsya kak x.operator[](y). Funkciya operator[]
dolzhna byt' nestaticheskoj funkciej-chlenom klassa x.
R.13.4.6 Dostup k chlenu klassa
Dostup k chlenu klassa opredelyaetsya s pomoshch'yu operacii ->:
pervichnoe-vyrazhenie -> pervichnoe-vyrazhenie
On schitaetsya unarnoj operaciej. Dlya ob容kta klassa x vyrazhenie x->m
interpretiruetsya kak (x.operator->())->m. Otsyuda sleduet, chto
funkciya operator->() dolzhna vozvrashchat' ili ukazatel' na klass, ili
ssylku na klass, ili ob容kt klassa, dlya kotorogo opredelena funkciya
operator->(). Ona dolzhna byt' nestaticheskoj funkciej-chlenom klassa.
R.13.4.7 Inkrement i dekrement
Funkciya s imenem operator++ i s odnim parametrom zadaet dlya ob容ktov
nekotorogo klassa operaciyu prefiksnogo inkrementa ++. Funkciya s
imenem operator++ i s dvumya parametrami zadaet dlya ob容ktov
nekotorogo klassa operaciyu postfiksnogo inkrementa ++. Dlya postfiksnoj
operacii ++ vtoroj parametr dolzhen byt' tipa int, i,
kogda v vyrazhenii vstrechaetsya operaciya postfiksnogo inkrementa,
funkciya operator++ vyzyvaetsya so vtorym parametrom, ravnym nulyu.
Privedem primer:
class X {
public:
X operator++(); // prefiksnaya ++a
X operator++(int) // postfiksnaya a++
};
void f(X a)
{
++a; // a.operator++();
a++; // a.operator++(0);
a.operator++(); // yavnyj vyzov: dejstvuet kak ++a;
a.operator++(0); // yavnyj vyzov: dejstvuet kak a++;
}
Prefiksnye i postfiksnye operacii dekrementa -- opredelyayutsya
analogichnym obrazom.
R.14 SHABLONY TIPA
R.14.1 SHablony tipa
SHablon tipa opredelyaet celoe semejstvo tipov ili funkcij.
opisanie-shablona-tipa:
template < spisok-parametrov-shablona-tipa> opisanie
spisok-parametrov-shablona-tipa:
parametr-shablona-tipa
spisok-parametrov-shablona-tipa , parametr-shablona-tipa
parametr-shablona-tipa:
parametr-tipa
opisanie-parametra
parametr-tipa:
class identifikator
Konstrukciya opisanie v opisanii-shablona-tipa dolzhna soderzhat'
opisanie ili opredelenie funkcii ili klassa.
V konstrukcii parametr-tipa identifikator opredelyaetsya kak imya-tipa
v oblasti vidimosti opisaniya shablona tipa.
Imena shablonov tipa podchinyayutsya obychnym pravilam dlya oblastej
vidimosti i kontrolya dostupa. Konstrukciya opisanie-shablona-tipa
schitaetsya opisaniem. Ona mozhet prisutstvovat' v programme tol'ko
kak global'noe opisanie.
R.14.2 SHablony tipov dlya klassov
SHablon tipa dlya klassa opredelyaet kak budut stroit'sya klassy, podobno
tomu, kak opisanie klassa opredelyaet kak budut stroit'sya ob容kty etogo
klassa. SHablon tipa dlya klassa vector mozhno opisat' sleduyushchim obrazom:
template<class T> class vector {
T* v;
int sz;
public:
vector(int);
T& operator[](int);
T& elem(int i) { return v[i] }
// ...
};
Prefiks template<class T> pokazyvaet, chto opisyvaetsya shablon tipa,
i chto v etom opisanii ispol'zuetsya imya-tipa T, inymi slovami,
vector - eto parametrizovannyj tip s parametrom T.
Klass mozhno zadat' s pomoshch'yu konstrukcii imya-shablonnogo-klassa:
imya-shablonnogo-klassa:
imya-shablona-tipa < spisok-param-shablona-tipa >
spisok-param-shablona-tipa:
param-shablona-tipa
spisok-param-shablona-tipa , param-shablona-tipa
param-shablona:
vyrazhenie
imya-tipa
Konstrukciya imya-shablonnogo-klassa yavlyaetsya imenem-klassa ($$R.9).
Klass, kotoryj porozhdaetsya shablonom tipa dlya klassa, nazyvaetsya
shablonnym klassom i ekvivalenten obychnomu klassu, opredelennomu so
special'nym imenem - imenem-shablonnogo-klassa, sm. $$R.14.5.
Esli v konstrukcii imya-shablonnogo-klassa imya-shablona-tipa ne opredeleno,
to ona oboznachaet neopredelennyj klass.
Imya shablonnogo klassa dolzhno byt' unikal'nym v programme i v svoej
oblasti vidimosti ono ne mozhet oboznachat' drugoj shablon tipa,
klass, funkciyu, ob容kt, znachenie ili tip.
Tipy, ukazannye v spiske-param-shablona-tipa iz
imeni-shablonnogo-klassa, dolzhny sootvetstvovat' tipam, zadannym
v spiske-parametrov-shablona-tipa iz shablona-tipa. (Mozhno skazat',
chto pervye yavlyayutsya fakticheskimi parametrami shablona tipa, a vtorye
- formal'nymi.)
Krome tipov v spiske-param-shablona-tipa mogut byt':
vyrazheniya-konstanty, adresa ob容ktov ili funkcij, podlezhashchih vneshnemu
svyazyvaniyu, staticheskie chleny klassov. Dlya parametrov, ne
yavlyayushchihsya tipami, trebuetsya tochnoe sootvetstvie ($$R.13.2).
Privedem primery ispol'zovaniya klassov shablona tipa vector:
vector<int> v1(20);
vector<complex> v2(30);
typedef vector<complex> cvec; // cvec stanovitsya sinonimom
// vector<complex>
cvec v3(40); // v2 i v3 odnogo tipa
v1[3] = 7;
v2[3] = v3.elem(4) = complex(7,8);
Zdes' vector<int> i vector<complex> yavlyayutsya shablonnymi klassami,
i ih opredeleniya berutsya po umolchaniyu iz shablona tipa vector.
Poskol'ku shablonnoe-imya-klassa yavlyaetsya imenem-klassa, to ono mozhet
ispol'zovat'sya tam, gde dopustimo imya-klassa, naprimer:
class vector<Shape*>
vector<Window>* current_window;
class svector : public vector<Shape*> { /* ... */ };
Opredelenie funkcii-chlena shablonnogo klassa dano v $$R.14.6.
R.14.3 |kvivalentnost' tipov
Dve konstrukcii shablonnoe-imya-klassa oboznachayut odin i tot zhe klass,
esli v nih sovpadayut imena shablonov tipa i znacheniya ukazannyh
parametrov. Naprimer, v sleduyushchih opisaniyah x i y odnogo tipa,
kotoryj otlichen ot tipa z:
template<class E, int size> class buffer;
buffer<char, 2*512> x;
buffer<char,1024> y;
buffer<char,512> z;
Nizhe privedeny opisaniya, v kotoryh odinakovyj tip imeyut x2 i x3.
On otlichaetsya ot tipov x1 i x4:
template<class T, void(*err_fct)()>
class list { /* ... */ };
list<int,&error_handler1> x1;
list<int,&error_handler2> x2;
list<int,&error_handler2> x3;
list<char,&error_handler2> x4;
R.14.4 SHablony tipa dlya funkcij
SHablon tipa dlya funkcii opredelyaet kak budet stroit'sya funkciya. Naprimer,
semejstvo funkcij sort mozhno opisat' sleduyushchim obrazom:
template<class T> void sort(vector<T>);
SHablon tipa dlya funkcii porozhdaet neogranichennoe mnozhestvo peregruzhennyh
funkcij. Funkciya, porozhdaemaya shablonom tipa dlya funkcij, nazyvaetsya
shablonnoj funkciej. Ona ekvivalentna funkcii, v opisanii kotoroj ukazan
tip, sootvetstvuyushchij shablonu, sm. $$R.14.5.
Pri vyzove shablonnoj funkcii parametry shablona tipa ne zadayutsya
yavno, vmesto etogo primenyaetsya pravilo razresheniya neopredelennosti
peregruzhennyh funkcij. Rassmotrim primer:
vector<complex> cv(100);
vector<int> ci(200);
void f(vector<complex>& cv, vector<int>& ci)
{
sort(cv); // vyzyvaetsya sort(vector<complex>)
sort(ci); // vyzyvaetsya sort(vector<int>)
}
SHablonnaya funkciya mozhet byt' peregruzhena kak obychnymi, tak i
shablonnymi funkciyami s tem zhe imenem. Dlya razresheniya neopredelennosti
shablonnyh i obychnyh funkcij s odnim i tem zhe imenem nado
posledovatel'no projti tri shaga:
[1] Popytat'sya najti tochno sopostavimuyu vyzovu ($$R.13.2) funkciyu,
i esli ona najdena, vyzvat' ee.
[2] Popytat'sya najti shablon tipa dlya funkcij, po kotoromu
mozhno sozdat' tochno sopostavimuyu s rassmatrivaemym vyzovom
funkciyu. Esli udalos' najti, to vyzvat' funkciyu.
[3] Popytat'sya primenit' obychnoe pravilo razresheniya neopredelennosti
peregruzhennyh funkcij ($$R.13.2). Esli s ego pomoshch'yu
funkciya najdena, vyzvat' ee.
Esli ne najdeno sopostavimoj funkcii, vyzov yavlyaetsya oshibochnym.
Esli uzhe na pervom shage najdeno bolee odnogo kandidata,
sopostavimogo s dannoj funkciej, to vyzov takzhe schitaetsya neodnoznachnym
i oshibochnym.
Uspeshnoe vypolnenie shaga [2] privedet k sozdaniyu nekotoroj
shablonnoj funkcii s parametrami ($$R.14.5), tipy kotoryh tochno
sopostavyatsya s tipami parametrov, ukazannyh v vyzove. V etom sluchae
nedopustimo rashozhdenie dazhe za schet trivial'nyh preobrazovanij ($$R.13.2).
Takie zhe dejstviya primenyayutsya dlya sopostavleniya tipov ukazatelej
na funkcii ($$R.13.3).
Rassmotrim primer:
template<class T> T max(T a, T b) { return a>b?a:b; };
void f(int a, int b, char c, char d)
{
int m1 = max(a,b); // max(int a, int b)
char m2 = max(c,d); // max(char c, char b)
int m3 = max(a,c); // oshibka: nel'zya sozdat' max(int,char)
}
Dobaviv k etomu primeru opisanie
int max(int,int);
mozhno razreshit' neopredelennost' dlya tret'ego vyzova, poskol'ku teper'
zadana funkciya, kotoraya posle standartnogo preobrazovaniya char v int,
mozhet sopostavit'sya s vyzovom max(a,c).
Opredelenie shablona tipa dlya funkcii ispol'zuetsya dlya sozdaniya
razlichnyh variantov shablona tipa. Dlya vyzova opredelennogo varianta
dostatochno lish' opisaniya shablona tipa.
Kazhdyj parametr-shablona-tipa, kotoryj priveden v
spiske-parametrov-shablona-tipa dolzhen obyazatel'no ispol'zovat'sya pri
zadanii tipov parametrov v shablone tipa dlya funkcii.
template<class T> T* create(); //oshibka
template<class T>
void f() { // oshibka
T a;
// ...
}
Vse parametry-shablona-tipa, privedennye v shablone tipa dlya funkcii,
dolzhny byt' parametrami-tipa.
R.14.5 Opisaniya i opredeleniya
Dlya kazhdogo imeni shablona tipa v programme dolzhno sushchestvovat' tol'ko
odno opredelenie. Opisanij mozhet byt' neskol'ko. Opredelenie
ispol'zuetsya dlya sozdaniya special'nyh shablonnyh klassov i shablonnyh
funkcij, kotorye budut sootvetstvovat' shablonu tipa.
Konstrukciya imya-shablonnogo-klassa vvodit opisanie shablonnogo klassa.
Vyzov shablonnoj funkcii ili vzyatie ee adresa vvodit opisanie
shablonnoj funkcii. Dlya vyzova ili vzyatiya adresa shablonnoj funkcii
v yazyke sushchestvuet osoboe soglashenie: imya shablonnoj funkcii
ispol'zuetsya tochno tak zhe kak imya obychnoj funkcii. Opisanie funkcii
s takim zhe imenem, kak u shablonnoj funkcii, i s sopostavimymi tipami
parametrov, vvodit opisanie special'noj shablonnoj funkcii.
Esli dlya vypolneniya nekotoryh operacij trebuetsya opredelenie
special'nogo shablonnogo klassa ili special'noj shablonnoj funkcii,
i esli takogo opredeleniya v programme net, to ono budet sozdano.
Opredelenie obychnoj (neshablonnoj) funkcii s tipom, kotoryj
tochno sopostavlyaetsya s tipom iz opisaniya shablonnoj funkcii,
schitaetsya opredeleniem special'noj shablonnoj funkcii. Rassmotrim
primer:
template<class T> void sort(vector<T>& v) { /* ... */ }
void sort(vector<char*>& v) { /* ... */ }
Zdes' opredelenie funkcii sort budet ispol'zovat'sya dlya toj funkcii
iz semejstva sort, kotoraya sopostavlyaetsya pri vyzove s tipom
parametra vector<char*>. Dlya drugih tipov vector budet sozdavat'sya
sootvetstvuyushchee im opredelenie funkcii po shablonu tipa.
Mozhno opredelit' klass, kotoryj zadaet shablonnyj klass, naprimer:
template<class T> class stream { /* ... */ };
class stream<char> { /* ... */ };
Zdes' opisanie klassa budet ispol'zovat'sya v kachestve opredeleniya
potoka simvolov (stream<char>). Drugie potoki budut upravlyat'sya
s pomoshch'yu shablonnyh funkcij, sozdavaemyh po shablonu tipa dlya funkcij.
Poka ne poyavitsya opisanie shablona tipa dlya klassa, nikakie operacii,
kotorym trebuetsya opredelennyj klass, ne mogut byt' proizvedeny nad
shablonnym klassom. Posle etogo special'nyj shablonnyj klass
budet schitat'sya opredelennym, prichem srazu zhe pered pervym global'nym
opisaniem, ispol'zuyushchim ego imya.
R.14.6 Funkcii-chleny shablonov tipa
Funkciya-chlen shablonnogo klassa schitaetsya neyavnoj shablonnoj funkciej,
a parametry shablona tipa dlya ee klassa - ee shablonnymi parametrami.
Privedem primer, v kotorom opisany tri shablona tipa dlya funkcii:
template<class T> class vector {
T* v;
int sz;
public:
vector(int);
T& operator[](int);
T& elem(int i) { return v[i]; }
// ...
};
Funkciyu, vypolnyayushchuyu indeksaciyu, mozhno opredelit' sleduyushchim obrazom:
template<class T> T& vector<T>::operator[](int i)
{
if (i<0 || sz>=i) error("vector: range error");
return v[i];
}
SHablonnyj parametr dlya vector<T>::operator[]() budet zadavat'sya
tem tipom vector, k kotoromu primenyaetsya operaciya indeksacii.
vector<int> v1(20);
vector<complex> v2(30);
v1[3] = 7; // vector<int>::operator[]()
v2[3] = complex(7,8); // vector<complex>::operator[]()
Funkciya-drug dlya shablona tipa ne yavlyaetsya neyavnoj shablonnoj funkciej,
naprimer:
template<class T> class task {
// ...
friend void next_time();
friend task<T>* preempt(task<T>*);
friend task* prmt(task*); // oshibka
// ...
};
Zdes' funkciya next_time() stanovitsya drugom vseh klassov task, a
kazhdyj klass task imeet v kachestve druga funkciyu preempt() c
sootvetstvuyushchimi tipami parametrov. Funkciyu preempt() mozhno
opredelit' kak shablon tipa.
template<class T>
task<T>* preempt(task<T>* t) { /* ... */ }
Opisanie funkcii prmt() yavlyaetsya oshibochnym, poskol'ku tipa
task ne sushchestvuet, a est' tol'ko special'nye shablonnye tipy
task<int>, task<record>, i t.d.
R.14.8 Staticheskie chleny i peremennye
Dlya kazhdogo shablonnogo klassa ili funkcii, sozdavaemyh po shablonu
tipa, obrazuetsya svoya kopiya staticheskih peremennyh ili chlenov.
Rassmotrim primer:
template<class T> class X {
static T s;
// ...
};
X<int> aa;
X<char*> bb;
Zdes' v klasse X<int> est' staticheskij chlen tipa int, a v klasse
X<char> est' staticheskij chlen tipa char*.
Analogichno, v privedennom nizhe primere, funkciya f(int*) imeet
staticheskij chlen s tipa int, a funkciya f(char**) imeet staticheskij
chlen tipa char**:
template<class T> f(T* p)
{
static T s;
// ...
}
void g(int a, char* b)
{
f(&a);
f(&b);
}
R.15 Obrabotka osobyh situacij
R.15.1 Obrabotka osobyh situacij
Pri obrabotke osobyh situacij v hode vypolneniya programmy informaciya i
upravlenie peredayutsya iz nekotoroj tochki obrabotchiku osobyh
situacij. Obrabotchik nahoditsya v cepochke vypolnennyh vyzovov
funkcij. Upravlenie obrabotchiku peredaetsya s pomoshch'yu
vyrazheniya-zapuska, kotoroe mozhet byt' tol'ko v proveryaemom-bloke
obrabotchika ili v funkcii, vyzvannoj iz proveryaemogo-bloka.
proveryaemyj-blok:
try sostavnoj-operator spisok-obrabotchikov
spisok-obrabotchikov:
obrabotchik spisok-obrabotchikov opt
obrabotchik:
catch ( opisanie-osoboj-situacii ) sostavnoj-operator
opisanie-osoboj-situacii:
spisok-specifikacij-tipa opisatel'
spisok-specifikacij-tipa abstraktnyj-opisatel'
spisok-specifikacij-tipa
...
vyrazhenie-zapuska:
throw vyrazhenie opt
Konstrukciya proveryaemyj-blok yavlyaetsya operatorom ($$R.6), a
vyrazhenie-zapuska - unarnym vyrazheniem tipa void ($$R.5). Inogda
vyrazhenie-zapuska nazyvayut "tochkoj zapuska", a pro funkciyu, v kotoroj
vstretilos' vyrazhenie-zapuska, govoryat, chto ona "zapuskaet osobuyu
situaciyu. CHast' programmy, kotoroj peredaetsya upravlenie iz tochki
zapuska nazyvaetsya obrabotchikom.
R.15.2 Zapusk osoboj situacii
Pri zapuske osoboj situacii upravlenie peredaetsya obrabotchiku. Zapusk
soprovozhdaetsya peredachej ob容kt, tip kotorogo opredelyaet, kakoj
obrabotchik dolzhen perehvatit' osobuyu situaciyu. Tak, vyrazhenie
throw "Help!";
mozhet byt' perehvacheno nekotorym obrabotchikom s tipom char*:
try {
// ...
}
catch(const char* p) {
// zdes' obrabatyvaetsya osobaya situaciya v simvol'nyh strokah
}
a osobaya situaciya Overflow (perepolnenie):
class Overflow {
// ...
public:
Overflow(char,double,double);
};
void f(double x)
{
// ...
throw Overflow('+',x,3.45e107);
}
mozhet byt' perehvachena obrabotchikom
try {
// ...
f(1.2);
// ...
}
catch(Overflow& oo) {
// zdes' obrabotka osoboj situacii tipa Overflow
}
Pri zapuske osoboj situacii upravlenie peredaetsya blizhajshemu
obrabotchiku sootvetstvuyushchego tipa. "Blizhajshij" - eto obrabotchik,
proveryaemyj-blok kotorogo poslednim poluchil upravlenie i ono eshche
ne bylo peredano ottuda. CHto takoe "sootvetstvuyushchij" tip
opredelyaetsya v $$R.15.4.
Pri vypolnenii vyrazheniya-zapuska sozdaetsya vremennyj ob容kt
staticheskogo tipa, kotoryj sluzhit operandom v komande throw,
|tot ob容kt ispol'zuetsya dlya inicializacii peremennoj,
sootvetstvuyushchego tipa, opisannoj v obrabotchike. Esli ne schitat'
ogranichenij na sopostavlenie tipov (sm. $$R.15.4) i ispol'zovanie
vremennoj peremennoj, to operand throw analogichen parametru funkcii
pri vyzove ($$R.5.2.2) ili operandu v operatore return.
Esli mozhno bylo by, ne menyaya smysla programmy za schet otkaza
ot vyzovov konstruktorov i destruktorov dlya vremennogo ob容kta
($$R.12.1), obojtis' sovsem bez vremennogo ob容kta, to osobuyu
situaciyu mozhno bylo by neposredstvenno inicializirovat' v obrabotchike
parametrom vyrazheniya zapuska.
Esli v vyrazhenii-zapuska operand ne zadan, to proishodit
perezapusk obrabotki osoboj situacii. Takoe vyrazhenie-zapuska
mozhet poyavitsya tol'ko v samom obrabotchike ili v funkcii, kotoraya
neposredstvenno ili oposredovanno vyzyvaetsya iz nego.
Naprimer, fragment programmy, kotoryj vypolnyaetsya pri obrabotke osoboj
situacii, esli nel'zya eshche polnost'yu provesti etu obrabotku, mozhet
vyglyadet' tak:
try {
// ...
}
catch (...) { // perehvat vseh osobyh situacij
// (chastichnaya) obrabotka osobyh situacij
throw; // peredacha ostal'nyh osobyh situacij drugomu obrabotchiku
}
R.15.3 Konstruktory i destruktory
Kogda upravlenie peredaetsya iz tochki zapuska osoboj situacii
obrabotchiku, to vyzyvayutsya destruktory dlya vseh avtomaticheskih
ob容ktov, postroennyh s momenta vhoda v proveryaemyj-blok.
Esli ob容kt ne byl postroen polnost'yu, to destruktory
vyzyvayutsya tol'ko dlya polnost'yu postroennyh vlozhennyh v nego ob容ktov.
Krome togo, esli osobaya situaciya zapuskaetsya v konstruktore pri
postroenii elementa avtomaticheskogo massiva, to unichtozhat'sya budut
tol'ko uzhe postroennye elementy etogo massiva.
Process vyzova destruktorov dlya unichtozheniya avtomaticheskih
ob容ktov, postroennyh v hode vypolneniya programmy ot nachala
proveryaemogo-bloka do vyrazheniya-zapuska, nazyvaetsya "raskruchivaniem
steka".
R.15.4 Obrabotka osoboj situacii
Obrabotchik tipa T, const T, T& ili const& sopostavim s
vyrazheniem-zapuska, imeyushchim operand tipa E, esli:
[1] T i E yavlyayutsya odnim tipom;
[2] T yavlyaetsya dostupnym ($$R.4.6) bazovym klassom E v tochke
zapuska;
[3] T yavlyaetsya tipom ukazatelya, a E yavlyaetsya takim tipom ukazatelya,
kotoryj mozhno v tochke zapuska preobrazovat' v T s pomoshch'yu
standartnyh preobrazovanij ukazatelya ($$R.4.6).
Rassmotrim primer:
class Matherr { /* ... */ virtual vf(); };
class Overflow : public Matherr { /* ... */ };
class Underflow : public Matherr { /* ... */ };
class Zerodivide : public Matherr { /* ... */ };
void f()
{
try {
g();
}
catch (Overflow oo) {
// ...
}
catch (Matherr mm) {
// ...
}
}
Zdes' obrabotchik Overflow budet perehvatyvat' situacii tipa
Overflow, a obrabotchik Matherr budet perehvatyvat' situacii tipa
Matherr i vseh tipov, yavlyayushchihsya obshchimi proizvodnymi ot Matherr,
vklyuchaya Underflow i Zerodivide.
Obrabotchiki v proveryaemom-bloke podbirayutsya dlya dannoj osoboj
situacii v poryadke ih opisaniya. Schitaetsya oshibkoj , esli obrabotchik
dlya bazovogo klassa pomeshchen pered obrabotchikom dlya proizvodnogo klassa,
poskol'ku pri takom raspolozhenii upravlenie nikogda ne popadet
k obrabotchiku dlya proizvodnogo klassa.
|llipsis ... v opisanii-osoboj-situacii dejstvuet tak zhe kak, i
v opisanii parametrov funkcii, on sopostavim s lyuboj osoboj
situaciej. Esli zadan ellipsis, to ispol'zuyushchij ego obrabotchik
dolzhen idti poslednim v proveryaemom-bloke.
Esli v proveryaemom-bloke ne proizoshlo sopostavleniya ni s odnim
iz obrabotchikov, poisk sootvetstvuyushchego obrabotchika prodolzhaetsya
v dinamicheski ob容mlyushchem proveryaemom-bloke. Esli vo vsej programme
ne proizoshlo sopostavleniya ni s odnim obrabotchikom, vyzyvaetsya
funkciya terminate() ($$R.15.7).
Osobaya situaciya schitaetsya obrabotannoj posle vhoda v telo
obrabotchika. V etot moment zavershitsya "raskruchivanie steka".
R.15.5 Specifikacii osobyh situacij
Vozniknovenie i perehvatyvanie osoboj situacii vliyaet na
vzaimodejstvie funkcij. Spisok osobyh situacij, kotorye pryamo ili
kosvenno mozhet zapustit' dannaya funkciya, mozhno zadat' kak chast' ee
opisaniya. Konstrukciya specifikaciya-osoboj-situacii
predshestvuet opisatelyu funkcii.
specifikaciya-osoboj-situacii:
throw ( spisok-tipov opt )
spisok-tipov:
imya-tipa
spisok-tipov , imya-tipa
Privedem primer:
void f() throw (X,Y)
{
// ...
}
Esli funkciya poprobuet zapustit' neukazannuyu v spiske situaciyu,
upravlenie peredaetsya funkcii unexpected(), sm. $$R.15.8.
Realizaciya yazyka ne dolzhna zapreshchat' vyrazhenie tol'ko potomu,
chto pri ego vychislenii vozmozhen zapusk osoboj situacii, ne ukazannoj
v specifikacii-osoboj situacii opisaniya funkcii. Obrabotka nepredvidennyh
osobyh situacij proishodit v dinamike.
Funkciya, v kotoroj otsutstvuet specifikaciya-osoboj-situacii,
mozhet zapustit' lyubuyu osobuyu situaciyu.
Funkciya s pustoj specifikaciej-osobyh-situacij (throw()) ne dolzhna
zapuskat' nikakih osobyh situacij.
Esli funkciya mozhet zapustit' osobuyu situaciyu klassa X, to ona
mozhet zapustit' osobuyu situaciyu lyubogo klassa, yavlyayushchegosya obshchim
proizvodnym klassom ot X.
Konstrukciya specifikaciya-osoboj-situacii ne otnositsya k tipu
funkcii.
R.15.6 Special'nye funkcii
Mehanizm upravleniya osobymi situaciyami ispol'zuet dlya reakcii na oshibki
pri samoj obrabotke osobyh situacij funkcii:
terminate() i unexpected().
R.15.6.1 Funkciya terminate()
Inogda ot predusmotrennoj obrabotki osobyh situacij prihoditsya
perehodit' k bolee grubym priemam, naprimer:
- kogda mehanizm upravleniya osobymi situaciyami ne smog najti
obrabotchik dlya zapushchennoj osoboj situacii;
- kogda mehanizm upravleniya osobymi situaciyami stolknulsya
s narushennoj strukturoj steka;
- kogda destruktor, vyzvannyj v processe raskrutki steka pri zapuske
osoboj situacii, sam pytaetsya zavershit' vypolnenie programmy,
zapustiv osobuyu situaciyu.
V etih sluchayah vyzyvaetsya funkciya
void terminate();
Ona v svoyu ochered' vyzyvaet funkciyu, kotoraya byla ukazana kak parametr
pri poslednem obrashchenii k set_terminate():
typedef void(*PFV)();
PFV set_terminate(PFV);
Funkciya, kotoraya byla zadana v predydushchem vyzove set_terminate(),
budet vozvrashchaemym znacheniem tekushchego vyzova. |to pomogaet
pol'zovatelyu realizovat' algoritm vosstanovleniya steka. Po umolchaniyu
funkciya terminate() vyzyvaet abort().
Vybor s pomoshch'yu terminate() takoj funkcii, kotoraya vmesto
dejstvitel'nogo zaversheniya programmy, pytaetsya vernut'sya v
vyzvavshuyu programmu, yavlyaetsya oshibkoj.
R.15.6.2 Funkciya unexpected()
Esli funkciya, imeyushchaya specifikaciyu-osoboj-situacii, zapuskaet
neukazannuyu osobuyu situaciyu, to vyzyvaetsya funkciya
void unexpected();
Ona v svoyu ochered' vyzyvaet funkciyu, kotoraya byla zadana kak
parametr pri poslednem obrashchenii k set_unexpected():
typedef void(*PFV)();
PFV set_unexpected(PFV);
Funkciya, kotoraya byla zadana v predydushchem vyzove set_unexpected(),
budet vozvrashchaemym znacheniem tekushchego vyzova. |to pomogaet
pol'zovatelyu realizovat' algoritm vosstanovleniya steka. Po umolchaniyu
unexpected() vyzyvaet terminate(). Poskol'ku po umolchaniyu
terminate() vyzyvaet abort(), rezul'tatom budet neposredstvennoe
i tochnoe obnaruzhenie oshibki.
R.15.7 Osobye situacii i pravila dostupa
Dlya formal'nogo parametra operacii catch dejstvuyut takie zhe
pravila dostupa, kak i dlya formal'nogo parametra funkcii, v kotoroj
zadana operaciya catch.
Pri zapuske osoboj situacii mozhno ukazyvat' takoj ob容kt, kotoryj
mozhno kopirovat' i unichtozhat' v oblasti vidimosti funkcii, gde
zadana operaciya throw.
R.16 Preprocessornaya obrabotka
Realizaciya yazyka S++ vklyuchaet preprocessor s vozmozhnostyami
makropodstanovki, uslovnoj translyacii i vklyucheniya ukazannyh
fajlov.
Dlya peredachi zadanij preprocessoru sluzhat stroki, nachinayushchiesya
s simvola # (pered nim mogut idti probely i simvoly gorizontal'noj
tabulyacii). Takie stroki nazyvayutsya komandami, i ih sintaksis
opredelyaetsya nezavisimo ot ostal'nogo yazyka. Komandy mogut
nahodit'sya v lyubom meste programmy, i ih dejstvie prodolzhaetsya
(nezavisimo ot pravil oblastej vidimosti S++) do konca dannoj
edinicy translyacii ($$R.2).
Komandu preprocessora, kak i lyubuyu stroku, mozhno prodolzhit' na
sleduyushchej stroke vhodnogo teksta, pomestiv simvol obratnoj
drobnoj cherty neposredstvenno pered simvolom konca prodolzhaemoj
stroki. Preprocessor do togo, kak vhodnaya stroka budet razbita na
leksemy, udalyaet simvoly obratnoj drobnoj cherty i konca stroki.
Simvol obratnoj drobnoj cherty ne dolzhen byt' poslednim simvolom
vhodnogo fajla.
K leksemam preprocessora otnosyatsya: leksemy samogo yazyka ($$R.2.1),
imya fajla, kotoroe ispol'zuetsya v komande #include i voobshche lyuboj
simvol, otlichnyj ot obobshchennogo probela i nesovpadayushchij ni s kakoj
iz leksem preprocessora.
R.16.1 Fazy preprocessornoj obrabotki
Po opredeleniyu sushchestvuet neskol'ko faz preprocessornoj obrabotki.
V konkretnoj realizacii fazy mogut slivat'sya, no rezul'tat vse ravno
dolzhen byt' takim, kak budto byli vypolneny vse fazy.
Perechislim ih.
Pri neobhodimosti simvoly, zavisyashchie ot sistemy simvoly, oboznachayushchie
konec stroki, zamenyayutsya na standartnyj simvol konca stroki. Analogichnoj
zamene podlezhat vse zavisyashchie ot sistemy simvoly. Opredelennye
posledovatel'nosti simvolov (trigrafy) zamenyayutsya na ekvivalentnyj
im otdel'nyj simvol ($$R.16.2).
Udalyayutsya vse takie pary simvolov: obratnaya drobnaya cherta, sleduyushchij
za nej simvol konca stroki. V rezul'tate budut slity stroki vhodnogo
teksta, iz kotoryh byla udalena eta para.
Vhodnoj tekst razbivaetsya na leksemy preprocessora i posledovatel'nost'
obobshchennyh probelov. Kazhdyj kommentarij zamenyaetsya na odin probel.
Vhodnoj tekst ne dolzhen konchat'sya posredi leksemy ili kommentariya.
Vypolnyayutsya komandy preprocessora, i proizvodyatsya makropodstanovki
($$R.16.3, $$R.16.4, $$R.16.5, $$R.16.6, $$R.16.7 i $$R.16.8).
V simvol'nyh konstantah i strokah literalov kombinacii special'nyh
simvolov zamenyayutsya na svoi ekvivalenty ($$R.2.5.2).
Slivayutsya sosednie stroki literalov.
Rezul'tat preprocessornoj obrabotki podvergaetsya sintaksicheskomu
i semanticheskomu analizu, transliruetsya, a zatem svyazyvaetsya s
neobhodimymi bibliotekami i drugimi programmami.
R.16.2 Trigrafnye posledovatel'nosti
Prezhde chem nachnetsya kakaya-libo inaya preprocessornaya obrabotka,
kazhdoe vhozhdenie trigrafnoj posledovatel'nosti zamenyaetsya na odin
simvol v sootvetstvii s privedennoj nizhe tablicej.
??= # ??( [
??/ \ ??) [
??' ^ ??! |
Naprimer, stroka
??=define arraycheck(a,b) a??(b??) ??!??! b??(a??)
preobrazuetsya v
#define arraycheck(a,b) a[b] || b[a]
R.16.3 Makroopredelenie i makropodstanovka
Komanda vida
#define identifikator stroka-leksem
nazyvaetsya makroopredeleniem. Ona ukazyvaet preprocessoru, chto nado
proizvesti zamenu vseh posleduyushchih vhozhdenij identifikatora na zadannuyu
posledovatel'nost' leksem, nazyvaemuyu strokoj zameny. Obobshchennye
probely, okruzhayushchie etu posledovatel'nost' leksem, otbrasyvayutsya.
Naprimer, pri opredelenii
#define SIDE 8
opisanie
char chessboard[side][side];
posle makropodstanovki primet vid
char chessboard[8][8];
Opredelennyj takim sposobom identifikator mozhno pereopredelit'
s pomoshch'yu drugoj komandy #define, no pri uslovii, chto stroki
zameny v oboih opredeleniyah sovpadayut. Vse simvoly obobshchennogo
probela, razdelyayushchie leksemy, schitayutsya identichnymi.
Komanda vida
identifikator ( identifikator, ... ,identifikator) stroka-leksem
nazyvaetsya makroopredeleniem s parametrami ili "funkcional'nym"
makroopredeleniem. V nem nedopustimy probely mezhdu pervym
identifikatorom i simvolom (. Opredelennyj takim sposobom
identifikator mozhno pereopredelit' s pomoshch'yu drugogo funkcional'nogo
makroopredeleniya, no pri uslovii, chto vo vtorom opredelenii
to zhe chislo i te zhe naimenovaniya parametrov, chto i v pervom, a obe
stroki zameny sovpadayut. Vse simvoly obobshchennogo probela, razdelyayushchie
leksemy, schitayutsya identichnymi.
Posleduyushchie vhozhdeniya identifikatora, opredelennogo v
funkcional'nom makroopredelenii, esli za nim sleduyut simvol
(, posledovatel'nost' leksem, razdelennyh zapyatymi, i simvol
), zamenyayutsya na stroku leksem iz makroopredeleniya. Obobshchennye
probely, okruzhayushchie stroku zameny, otbrasyvayutsya. Kazhdoe vhozhdenie
identifikatora, iz spiska parametrov makroopredeleniya, zamenyaetsya
na posledovatel'nost' leksem, predstavlyayushchuyu sootvetstvuyushchij
fakticheskij parametr v makrovyzove. Fakticheskimi parametrami yavlyayutsya
stroki leksem, razdelennye zapyatymi. Zapyataya, vzyataya v kavychki, ili
nahodyashchayasya v simvol'noj konstante ili vo vlozhennyh kruglyh skobkah,
ne razdelyaet parametrov. CHislo fakticheskih parametrov makrovyzova dolzhno
sovpadat' s chislom parametrov makroopredeleniya.
Posle identifikacii parametrov dlya funkcional'nogo makroopredeleniya
proishodit podstanovka fakticheskih parametrov. Posle vypolneniya podstanovok
v parametre (esli oni byli) etot parametr v stroke zameny zameshchaetsya
fakticheskim parametrom iz makrovyzova ($$R.16.3.3); isklyucheniya
sostavlyayut sluchai, kogda parametru predshestvuet leksema # ($$R.16.3.1),
ili s nim sosedstvuet leksema ## ($$R.16.3.2).
Privedem primer. Pust' est' makroopredeleniya
#define index_mask 0XFF00
#define extract(word,mask) word & mask
Togda makrovyzov
index = extract(packed_data,index_mask);
posle podstanovki primet vid
index = packed_data & 0XFF00;
Dlya oboih vidov makroopredelenij stroka zameny proveryaetsya na
nalichie drugih makroopredelenij ($$R.16.3.3).
Esli neposredstvenno pered parametrom v stroke zameny idet leksema
#, to pri podstanovke parametr i operaciya # budut zameneny
na stroku literalov , soderzhashchuyu imya sootvetstvuyushchego parametra
makrovyzova. V simvol'noj konstante ili stroke literalov, vhodyashchih
v parametr, pered kazhdym vhozhdeniem \ ili " vstavlyaetsya simvol \.
Naprimer, esli est' makroopredeleniya
#define path(logid,cmd) "/usr/" #logid "/bin/" #cmd
to makrovyzov
char* mytool=path(joe,readmail);
privedet k takomu rezul'tatu:
char* mytool="/usr/" "joe" "/bin/" "readmail";
Posle konkatenacii sosednih strok ($$R.16.1) poluchim:
char* mytool="/usr/joe/bin/readmail";
Esli v stroke zameny mezhdu dvumya leksemami, odna iz kotoryh
predstavlyaet parametr makroopredeleniya, poyavlyaetsya operaciya
##, to sama operaciya ## i okruzhayushchie ee obobshchennye probely
udalyayutsya. Takim obrazom, rezul'tat operacii ## sostoit v
konkatenacii.
Pust' est' makroopredelenie,
#define inherit(basenum) public Pubbase ## basenum, \
private Privbase ## basenum
togda makrovyzov
class D : inherit(1) { };
privedet k takomu rezul'tatu:
class D : public Pubbase1, Privbase1 { };
Makroopredelenie, kotoroe v stroke zameny sosedstvuet s
##, ne podlezhit podstanovke, odnako, rezul'tat konkatenacii mozhet
ispol'zovat'sya dlya podstanovki. Privedem primer. Pust' est'
opredeleniya:
#define concat(a) a ## ball
#define base B
#define baseball sport
Togda makrovyzov
concat(base)
dast v rezul'tate
sport
a vovse ne
Bball
R.16.3.3 Povtornyj prosmotr i dal'nejshie podstanovki
Posle togo, kak v stroke zameny proizoshla podstanovka vseh parametrov
makrovyzova, poluchivshayasya stroka prosmatrivaetsya povtorno dlya
obnaruzheniya dopolnitel'nyh makroopredelenij. Esli v processe
povtornyh prosmotrov stroki zameny najdeno imya makroopredeleniya, to
podstanovka vse zhe ne proishodit.
Rekursivnuyu podstanovku nel'zya vypolnit' kak komandu
preprocessora, hotya ona kazhetsya dlya nego estestvennoj komandoj.
R.16.3.4 Oblast' vidimosti makroimen i konstrukciya #undef
Posle poyavleniya makroopredeleniya identifikator iz nego schitaetsya
opredelennym i ostaetsya v tekushchej oblasti vidimosti (nezavisimo ot
pravil oblastej vidimosti v S++) do konca edinicy translyacii ili
poka ego opredelenie ne budet otmeneno s pomoshch'yu komandy #undef.
Komanda #undef imeet vid:
#undef identifikator
Ona zastavlyaet preprocessor "zabyt'" makroopredelenie s etim
identifikatorom. Esli ukazannyj identifikator ne yavlyaetsya
opredelennym v dannyj moment makroimenem, to komanda #undef
ignoriruetsya.
R.16.4 Vklyuchenie fajlov
Upravlyayushchaya stroka vida:
#include <imyafajla>
privodit k zamene dannoj stroki na soderzhimoe fajla s ukazannym imenem.
Poisk ukazannogo fajla prohodit v opredelennoj posledovatel'nosti
chastej arhiva sistemy i opredelyaetsya realizaciej.
Analogichno, upravlyayushchaya stroka vida:
#include "imyafajla"
privodit k zamene dannoj stroki na soderzhimoe fajla s ukazannym
imenem. Poisk etogo fajla nachinaetsya v osobyh (sistemnyh) chastyah
arhiva, ukazannyh v nachale posledovatel'nosti poiska. Esli tam on
ne najden, to poisk fajla idet po vsej posledovatel'nosti, kak esli by
upravlyayushchaya stroka imela vid:
#include <imyafajla>
V imeni fajla, ogranichennom simvolami < i > nel'zya ispol'zovat'
simvoly konca stroki ili >. Esli v takom imeni poyavitsya odin iz
simvolov ', \, ili ", a takzhe posledovatel'nost' simvolov /* ili //,
to rezul'tat schitaetsya neopredelennym.
V imeni fajla, ogranichennom paroj simvolov " nel'zya ispol'zovat'
simvoly konca stroki ili ", hotya simvol > dopustim. Esli v takom
imeni poyavitsya simvol ' ili \ ili posledovatel'nost' /* ili //,
to rezul'tat schitaetsya neopredelennym.
Esli komanda
#include stroka-leksem
imeet vid, sootvetstvuyushchij ni pervoj, ni vtoroj upravlyayushchej stroke,
to leksemy preprocessora, zadannye v etoj komande obrabatyvayutsya kak
obychnyj tekst. V rezul'tate dolzhna poluchit'sya komanda, vid kotoroj
sootvetstvuet odnomu iz privedennyh. Ona i budet vypolnena kak polozheno.
Komanda #include mozhet byt' v fajle, kotoryj sam poyavilsya v
rezul'tate vypolneniya drugoj komandy #include.
Realizaciya mozhet nakladyvat' ogranichenie na glubinu vlozhennosti
komandy #include vo vhodnyh fajlah programmy, kotorye prihoditsya
chitat' dlya vypolneniya pervonachal'noj komandy #include v odnom iz
vhodnyh fajlov.
R.16.5 Uslovnaya translyaciya
S pomoshch'yu preprocessora mozhno organizovat' uslovnuyu translyaciyu
programmy. Sintaksicheski eto zadaetsya sleduyushchim obrazom:
uslovnoe:
chast'-if chasti-elif opt chast'-else opt stroka-endif
chast'-if:
stroka-if tekst
stroka-if:
# if vyrazhenie-konstanta
# ifdef identifikator
# ifndef identifikator
chasti-elif:
stroka-elif tekst
chasti-elif stroka-elif tekst
stroka-elif:
# elif vyrazhenie-konstanta
chast'-else:
stroka-else tekst
stroka-else:
# else
stroka-endif:
# endif
Konstantnye vyrazheniya v #if i #elif (esli eti chasti est')
vychislyayutsya v poryadke ih zadaniya v tekste do teh por, poka odno
iz nih ne okazhetsya otlichnym ot nulya. Operatory S++, sleduyushchie za
strokoj, v kotoroj vyrazhenie okazalos' ravnym nulyu, ne transliruyutsya.
Komandy preprocessora, idushchie za etoj strokoj ignoriruyutsya.
Posle togo, kak najdena komanda s nenulevym znacheniem vyrazheniya,
tekst vseh posleduyushchih chastej #elif i #else (t.e. operatory S++ i
komandy preprocessora) ignoriruetsya. Tekst, otnosyashchijsya k pervoj
komande s nenulevym znacheniem vyrazheniya podlezhit obychnoj preprocessornoj
obrabotke i translyacii. Esli znacheniya vseh vyrazhenij, ukazannyh v #if
i #elif, okazalis' ravnymi nulyu, togda obychnoj obrabotke podlezhit tekst,
otnosyashchijsya k #else.
V vyrazhenii-konstante, kotoroe vstretilos' v #if ili #elif
mozhno ispol'zovat' unarnuyu operaciyu defined, prichem v dvuh
variantah:
defined identifikator
ili
defined (identifikator)
Esli eta operaciya primenyaetsya k identifikatoru, kotoryj byl opredelen
s pomoshch'yu komandy #define, i esli eto opredelenie ne bylo otmeneno
komandoj #undef, to rezul'tat raven 1, inache rezul'tat raven 0.
Sam identifikator defined nel'zya pereopredelit', nel'zya i otmenit'
ego opredelenie.
Posle primeneniya operacij defined proishodit raskrytie vseh
vseh makroopredelenij, imeyushchihsya v konstantnom vyrazhenii
sm. $$R.16.3. V rezul'tate dolzhno poluchit'sya celochislennoe
vyrazhenie-konstanta, otlichayushcheesya ot opredeleniya v $$R.5.19 tem,
chto tipy int i unsigned int rassmatrivayutsya kak long i unsigned long
sootvetstvenno, a krome togo v etom vyrazhenii ne dolzhno byt'
operacij privedeniya, sizeof ili elementa perechisleniya.
Upravlyayushchaya stroka
#ifdef identifikator
ekvivalentna stroke
#if defined identifikator
a upravlyayushchaya stroka
#ifndef identifikator
ekvivalentna stroke
#if !defined identifikator
Konstrukcii, zadayushchie uslovnuyu translyaciyu, mogut byt' vlozhennymi,
no realizaciya mozhet nakladyvat' ogranichenie na glubinu vlozhennosti
etih konstrukcij.
R.16.6 Upravlenie strokami
Dlya udobstva napisaniya programm, porozhdayushchih tekst na S++, vvedena
upravlyayushchaya stroka vida:
#line konstanta "imyafajla" opt
Ona zadaet znachenie predopredelennomu makroimeni __LINE__ ($$R.16.10),
kotoroe ispol'zuetsya v diagnosticheskih soobshcheniyah ili pri
simvolicheskoj otladke; a imenno: nomer sleduyushchej stroki
vhodnogo teksta schitaetsya ravnym zadannoj konstante, kotoraya dolzhna
byt' desyatichnym celym chislom. Esli zadano "imyafajla", to znachenie
makroimeni __FILE__ ($$R.16.10) stanovitsya ravnym imeni ukazannogo
fajla. Esli ono ne zadano, __FILE__ ne menyaet svoego znacheniya.
Makroopredeleniya v etoj upravlyayushchej stroke raskryvayutsya do
vypolneniya samoj komandy.
Stroka vida:
#error stroka-leksem
zastavlyaet realizaciyu vydat' diagnosticheskoe soobshchenie, sostoyashchee
iz zadannoj posledovatel'nosti leksem preprocessora.
Stroka vida:
#pragma stroka-leksem
zastavlyaet realizaciyu vesti sebya nekotorym opredelennym obrazom
pri uslovii chto realizaciya "ponimaet" etu stroku. Lyubaya
neraspoznannaya stroka #pragma ignoriruetsya.
Komanda preprocessora vida
#
ne okazyvaet nikakogo dejstviya.
R.16.10 Predopredelennye makroimena
V processe translyacii opredelennuyu informaciyu soderzhat sleduyushchie
predopredelennye makroimena.
__LINE__ desyatichnaya konstanta, soderzhashchaya nomer tekushchej stroki
teksta programmy na S++.
__FILE__ stroka literalov, predstavlyayushchaya imya transliruemogo
vhodnogo fajla.
__DATE__ stroka literalov, predstavlyayushchaya datu translyacii v vide
"Mmm dd yyyy" ili "Mmm d yyyy", esli chislo men'she 10,
(zdes' Mmm zadaet mesyac, dd - den', a yyyy - god).
__TIME__ stroka literalov, predstavlyayushchaya vremya translyacii v vide
"hh:mm:ss", (zdes' hh zadaet chasy, mm - minuty, a
ss - sekundy).
Krome togo, schitaetsya opredelennym pri translyacii programmy na S++
makroimya __cplusplus.
Perechislennye makroimena nel'zya kak pereopredelyat', tak i otmenyat' ih
opredeleniya.
Makroimena __LINE__ i __FILE__ mozhno opredelit' s pomoshch'yu komandy
#line ($$R.16.6).
Opredeleno li makroimya __STDC, i esli da, to kakovo ego znachenie,
zavisit ot realizacii.
R.17 Prilozhenie A: Svodka grammatiki
|to prilozhenie ne otnositsya k spravochnomu rukovodstvu yazyka i
ne yavlyaetsya opredeleniem konstrukcij C++.
Ona tol'ko dolzhno sluzhit' bolee polnomu ponimaniyu S++. Nel'zya
rassmatrivat' ego kak tochnoe opredelenie yazyka, tak kak opisannaya zdes'
grammatika dopuskaet proizvol'noe mnozhestvo konstrukcij, kazhdaya iz
kotoryh zakonna dlya S++. CHtoby razlichat' vyrazheniya i opisaniya,
sleduet primenyat' pravila razresheniya neopredelennosti ($$r.6.8,
$$R.7.1, $$R.10.1.1). Dalee, dlya otseivaniya sintaksicheski pravil'nyh,
no bessmyslennyh, konstrukcij sleduet primenyat' pravila kontrolya
dostupa, razresheniya neopredelennosti i kontrolya tipa.
V opisaniyah: typedef ($$R.7.1.3), klassa ($$R.9), perechisleniya
($$R.7.2), shablona tipa - ($$R.14) vvedeny novye, zavisyashchie ot
konteksta, sluzhebnye slova, a imenno:
imya-klassa:
identifikator
imya-perechisleniya:
identifikator
imya-typedef:
identifikator
Otmetim, chto imya-typedef, oboznachayushchee klass, yavlyaetsya v to zhe
vremya konstrukciej imya-klassa ($$R.9.1).
vyrazhenie:
vyrazhenie-prisvaivaniya
vyrazhenie, vyrazhenie-prisvaivaniya
vyrazhenie-prisvaivaniya:
vyrazhenie-usloviya
unarnoe-vyrazhenie operaciya-prisvaivaniya vyrazhenie-prisvaivaniya
operaciya-prisvaivaniya: odin iz
= *= /= %= += -= >>= <<= &= ^= |=
vyrazhenie-usloviya:
logicheskoe-vyrazhenie-ILI
logicheskoe-vyrazhenie-ILI ? vyrazhenie : vyrazhenie-usloviya
logicheskoe-vyrazhenie-ILI:
logicheskoe-vyrazhenie-I
logicheskoe-vyrazhenie-ILI || logicheskoe-vyrazhenie-I
logicheskoe-vyrazhenie-I:
vyrazhenie-ILI
logicheskoe-vyrazhenie-I && vyrazhenie-ILI
vyrazhenie-ILI:
vyrazhenie-isklyuchayushchego-ILI
vyrazhenie-ILI | vyrazhenie-isklyuchayushchego-ILI
vyrazhenie-isklyuchayushchego-ILI:
vyrazhenie-I
vyrazhenie-isklyuchayushchego-ILI ^ vyrazhenie-I
vyrazhenie-I:
vyrazhenie-ravenstva
vyrazhenie-I & vyrazhenie-ravenstva
vyrazhenie-ravenstva:
vyrazhenie-otnosheniya
vyrazhenie-ravenstva == vyrazhenie-otnosheniya
vyrazhenie-ravenstva != vyrazhenie-otnosheniya
vyrazhenie-otnosheniya:
sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya < sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya > sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya <= sdvigovoe-vyrazhenie
vyrazhenie-otnosheniya >= sdvigovoe-vyrazhenie
sdvigovoe-vyrazhenie:
additivnoe-vyrazhenie
sdvigovoe-vyrazhenie << additivnoe vyrazhenie
sdvigovoe-vyrazhenie >> additivnoe vyrazhenie
additivnoe-vyrazhenie:
mul'tiplikativnoe-vyrazhenie
additivnoe vyrazhenie + mul'tiplikativnoe-vyrazhenie
additivnoe-vyrazhenie - mul'tiplikativnoe-vyrazhenie
mul'tiplikativnoe-vyrazhenie:
vyrazhenie-pm
mul'tiplikativnoe-vyrazhenie * vyrazhenie-pm
mul'tiplikativnoe-vyrazhenie / vyrazhenie-pm
mul'tiplikativnoe-vyrazhenie % vyrazhenie-pm
vyrazhenie-pm:
vyrazhenie-privedeniya
vyrazhenie-pm .* vyrazhenie-privedeniya
vyrazhenie-pm ->* vyrazhenie-privedeniya
vyrazhenie-privedeniya:
unarnoe-vyrazhenie
( imya-tipa ) vyrazhenie-privedeniya
unarnoe-vyrazhenie:
postfiksnoe-vyrazhenie
++ unarnoe vyrazhenie
-- unarnoe vyrazhenie
unarnaya-operaciya vyrazhenie-privedeniya
sizeof unarnaya-operaciya
sizeof ( imya-tipa )
vyrazhenie-razmeshcheniya
vyrazhenie-osvobozhdeniya
unarnaya-operaciya: odin iz
* & + - ! ~
vyrazhenie-razmeshcheniya:
::opt new parametry-new opt imya-tipa-new inicializator-new
::opt new parametry-new opt ( imya-tipa ) inicializator-new
parametry-new:
( spisok-vyrazhenij )
imya-tipa-new:
spisok-specifikacij-tipa opisatel'-new opt
opisatel'-new:
* spisok-specifikacij-cv opt opisatel'-new opt
imya-klassa :: spisok-specifikacij-cv opt opisatel'-new opt
opisatel'-new opt [ vyrazhenie ]
inicializator-new:
( spisok-inicializatorov opt )
vyrazhenie-osvobozhdeniya:
::opt delete vyrazhenie-privedeniya
::opt delete [] vyrazhenie-privedeniya
postfiksnoe-vyrazhenie:
pervichnoe-vyrazhenie
postfiksnoe-vyrazhenie [ vyrazhenie ]
postfiksnoe-vyrazhenie ( spisok-vyrazhenij opt )
imya-prostogo-tipa ( spisok-vyrazhenij opt )
postfiksnoe-vyrazhenie . imya
postfiksnoe-vyrazhenie -> imya
postfiksnoe-vyrazhenie ++
postfiksnoe-vyrazhenie --
spisok-vyrazhenij:
vyrazhenie-prisvaivaniya
spisok-vyrazhenij , vyrazhenie-prisvaivaniya
pervichnoe-vyrazhenie:
literal
this
:: identifikator
:: imya-funkcii-operacii
:: utochnennoe-imya
( vyrazhenie )
imya
imya:
identifikator
imya-funkcii-operacii
imya-funkcii-preobrazovaniya
~imya-klassa
utochnennoe-imya
utochnennoe-imya:
utochnyayushchee-imya-klassa :: imya
literal:
celaya konstanta
simvol'naya konstanta
konstanta s plavayushchej tochkoj
stroka literalov
opisaniya:
specifikacii-opisaniya opt spisok-opisatelej opt ;
opisanie-asm
opredelenie-funkcii
specifikaciya-svyazi
specifikaciya-opisaniya:
specifikaciya-klassa-pamyati
specifikaciya-tipa
specifikaciya-fct
specifikaciya-shablona-tipa
friend
typedef
specifikacii-opisaniya:
specifikacii-opisaniya opt specifikaciya-opisaniya
specifikaciya-klassa-pamyati:
auto
register
static
extern
specifikaciya-fct:
inline
virtual
specifikaciya-tipa:
imya-prostogo-tipa
specifikaciya-klassa
specifikaciya-perechisleniya
specifikaciya-slozhnogo-tipa
:: imya-klassa
const
volatile
imya-prostogo-tipa:
polnoe-imya-klassa
utochnennoe-imya-tipa
char
short
int
long
signed
unsigned
float
double
void
specifikaciya-slozhnogo-tipa:
sluzhebnoe-slovo-klassa imya-klassa
sluzhebnoe-slovo-klassa identifikator
sluzhebnoe-slovo-klassa:
class
struct
union
utochnennoe-imya-tipa:
imya-typedef
imya-klassa :: utochnennoe-imya-tipa
polnoe-imya-klassa:
utochnennoe-imya-klassa
:: utochnennoe-imya-klassa
utochnennoe-imya-klassa:
imya-klassa
imya-klassa :: utochnennoe-imya-klassa
imya-perechisleniya:
identifikator
specifikaciya-perechisleniya:
enum identifikator opt { spisok-perechisleniya }
spisok-perechisleniya:
element-perechisleniya
spisok-perechisleniya , element-perechisleniya
element-perechisleniya:
identifikator
identifikator = vyrazhenie-konstanta
specifikaciya-svyazi:
extern stroka-literal { spisok-opisanij opt }
extern stroka-literal opisanie
spisok-opisanij:
opisanie
spisok-opisanij opisanie
opisanie-asm:
asm ( stroka-literal) ;
spisok-opisanij:
opisatel'-s-inicializatorom
spisok-opisanij , opisatel'-s-inicializatorom
opisatel'-s-inicializatorom:
opisatel' inicializator opt
opisatel':
imya-v-opisatele
operaciya-ptr opisatel'
opisatel' (spisok-opisanij-parametrov) spisok-specifikacij-cv opt
opisatel' [ vyrazhenie-konstanta opt]
( opisatel' )
operaciya-ptr:
* spisok-specifikacij-cv opt
& spisok-specifikacij-cv opt
polnoe-imya-klassa :: * spisok-specifikacij-cv opt
spisok-specifikacij-cv:
const
volatile
imya-v-opisatele:
imya
imya-klassa
~imya-klassa
imya-typedef
utochnennoe-imya-tipa
imya-tipa:
spisok-specifikacij-tipa abstraktnyj-opisatel' opt
spisok-specifikacij-tipa:
specifikaciya-tipa spisok-specifikacij-tipa
abstraktnyj-opisatel':
operaciya-ptr abstraktnyj-opisatel' opt
abstraktnyj-opisatel' opt ( spisok-opisanij-parametrov ) spisok-specifikacij_cv opt
abstraktnyj-opisatel' opt [ vyrazhenie-konstanta opt ]
( abstraktnyj-opisatel' )
spisok-opisanij-parametrov:
spisok-opisanij-param opt ... opt
spisok-opisanij-param , ...
spisok-opisanij-param:
opisanie-parametra
spisok-opisanij-param , opisanie-parametra
opisanie-parametra:
specifikacii-opisaniya opisatel'
specifikacii-opisaniya opisatel' = vyrazhenie
specifikacii-opisaniya abstraktnyj-opisatel' opt
specifikacii-opisaniya abstraktnyj-opisatel' opt = vyrazhenie
opredelenie-funkcii:
specifikacii-opisaniya opt opisatel' inicializator-ctor telo-funkcii
telo-funkcii:
sostavnoj-operator
inicializator:
= vyrazhenie-prisvaivaniya
= { spisok-inicializatorov , opt }
( spisok-vyrazhenij )
spisok-inicializatorov:
vyrazhenie-prisvaivaniya
spisok-inicializatorov , vyrazhenie-prisvaivaniya
{ spisok-inicializatorov , opt }
specifikaciya-klassa:
zagolovok-klassa { spisok-chlenov opt }
zagolovok-klassa:
sluzhebnoe-slovo-klassa identifikator opt spec-bazovyh opt
sluzhebnoe-slovo-klassa imya-klassa spec-bazovyh opt
sluzhebnoe-slovo-klassa:
class
struct
union
spisok-chlenov:
opisanie-chlena spisok-chlenov opt
specifikaciya-dostupa : spisok-chlenov opt
opisanie-chlena:
specifikacii-opisaniya opt spisok-opisatelej-chlenov opt ;
opredelenie-funkcii ; opt
utochnennoe-imya ;
spisok-opisatelej-chlenov:
opisatel'-chlena
spisok-opisatelej-chlenov , opisatel'-chlena
opisatel'-chlena:
opisatel' specifikaciya-chistoj opt
identifikator opt : vyrazhenie-konstanta
specifikaciya-chistoj:
= 0
spisok-bazovyh:
specifikaciya-bazovyh
spisok-bazovyh , specifikaciya-bazovyh
specifikaciya-bazovyh:
polnoe-imya-klassa
virtual specifikaciya-dostupa opt polnoe-imya-klassa
specifikaciya-dostupa virtual opt polnoe-imya-klassa
specifikaciya-dostupa:
private
protected
public
imya-funkcii-preobrazovaniya:
operator imya-tipa-preobrazovaniya
imya-tipa-preobrazovaniya:
spisok-specifikacij-tipa operaciya-ptr opt
inicializator-ctor:
: spisok-inicializatorov-chlenov
spisok-inicializatorov-chlenov:
inicializator-chlena
inicializator-chlena , spisok-inicializatorov-chlena
inicializator-chlena:
polnoe-imya-klassa ( spisok-vyrazhenij opt )
identifikator
imya-funkcii-operator:
operator operaciya
operaciya: odin iz
new delete
+ - * / % ^ & | ~
! = < > += -= *= /= %=
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- , ->* ->
() []
operator:
pomechennyj-operator
operator-vyrazhenie
sostavnoj-operator
vybirayushchij-operator
operator-cikla
operator-perehoda
operator-opisaniya
pomechennyj-operator:
identifikator : operator
case vyrazhenie-konstanta : operator
default : operator
operator-vyrazhenie:
vyrazhenie opt ;
sostavnoj-operator:
{ spisok-operatorov opt }
spisok-operatorov:
operator
spisok-operatorov operator
vybirayushchij-operator:
if ( vyrazhenie ) operator
if ( vyrazhenie ) operator else operator
switch ( vyrazhenie ) operator
operator-cikla:
while ( vyrazhenie ) operator
do operator while (vyrazhenie)
for ( operator-inic vyrazhenie opt ; vyrazhenie opt ) operator
operator-inic:
operator-vyrazhenie
operator-opisanie
operator-perehoda:
break ;
continue ;
return vyrazhenie opt ;
goto identifikator ;
operator-opisaniya:
opisanie
#define identifikator stroka-leksem
#define identifikator ( identifikator , ... , identifikator ) stroka-leksem
#include "imyafajla"
#include <imyafajla>
#line konstanta "imyafajla" opt
#undef identifikator
uslovnoe:
chast'-if chasti-elif opt chast'-else opt stroka-endif
chast'-if:
stroka-if tekst
stroka-if:
# if vyrazhenie-konstanta
# ifdef identifikator
# ifndef identifikator
chasti-elif:
stroka-elif tekst
chasti-elif stroka-elif tekst
stroka-elif:
# elif vyrazhenie-konstanta
chast'-else:
stroka-else tekst
stroka-else:
# else
stroka-endif:
# endif
opisanie-shablona-tipa:
template < spisok-parametrov-shablona-tipa> opisanie
spisok-parametrov-shablona-tipa:
parametr-shablona-tipa
spisok-parametrov-shablona-tipa , parametr-shablona-tipa
parametr-shablona-tipa:
parametr-tipa
opisanie-parametra
parametr-tipa:
class identifikator
imya-shablonnogo-klassa:
imya-shablona-tipa < spisok-param-shablona-tipa >
spisok-param-shablona-tipa:
param-shablona-tipa
spisok-param-shablona-tipa , param-shablona-tipa
param-shablona:
vyrazhenie
imya-tipa
R.17.9 Obrabotka osobyh situacij
proveryaemyj-blok:
try sostavnoj-operator spisok-obrabotchikov
spisok-obrabotchikov:
obrabotchik spisok-obrabotchikov opt
obrabotchik:
catch ( opisanie-osoboj-situacii ) sostavnoj-operator
opisanie-osoboj-situacii:
spisok-specifikacij-tipa opisatel'
spisok-specifikacij-tipa abstraktnyj-opisatel'
spisok-specifikacij-tipa
...
vyrazhenie-zapuska:
throw vyrazhenie opt
specifikaciya-osoboj-situacii:
throw ( spisok-tipa opt )
spisok-tipa:
imya-tipa
spisok-tipa , imya-tipa
R.18 Prilozhenie B: Sovmestimost'
|to prilozhenie ne otnositsya k spravochnomu rukovodstvu S++ i ne
yavlyaetsya opredeleniem konstrukcij yazyka.
YAzyk S++ osnovyvaetsya na S (opisanie v knige Kernigana i Ritchi,
78 g., dal'she K&R) i vklyuchaet bol'shinstvo izmenenij, predlozhennyh
v ANSI standarte dlya S. Pri konvertirovanii programm na yazykah
S++, K&R C i ANSI C mogut vozniknut' trudnosti v svyazi s razlichnym
vychisleniem v nih vyrazhenij. Translyator dolzhen raspoznavat' vse razlichiya
mezhdu S++ i ANSI C. Programmy na S++ i ANSI C dolzhny imet' odinakovyj
smysl za isklyucheniem treh sleduyushchih sluchaev:
V yazyke S vyrazhenie sizeof('a') ravno sizeof(int), a v S++
ono ravno sizeof(char).
Esli est' opisanie
enum e { A };
to sizeof(A) ravno v S sizeof(int), togda kak v S++ ono ravno sizeof(e)
i ne obyazano byt' ravno sizeof(int).
Imya struktury, opisannoj vo vnutrennem bloke, mozhet skryvat' imya
ob容kta, funkcii, elementa perechisleniya ili tipa iz vneshnego bloka.
Privedem primer:
int x[99];
void f()
{
struct x { int a; };
sizeof(x); /* dlya C eto razmer massiva */
/* a dlya C++ razmer struktury */
}
V etom razdele perechislyayutsya osnovnye rasshireniya yazyka S, vvedennye
v S++.
R.18.1.1 Vozmozhnosti S++, vvedennye v 1985 g.
Zdes' perechislyayutsya vozmozhnosti, dobavlennye k S, versiej yazyka
S++ 1985 g.
Mozhno ukazyvat' tipy formal'nyh parametrov funkcii ($$R.8.2.5), i oni
budut proveryat'sya ($$R.5.2.2). Budet proishodit' preobrazovanie
tipa ($$R.5.2.2). |to est' i v ANSI C.
V vyrazheniyah so znacheniyami tipa float vychisleniya mogut prohodit'
s obychnoj tochnost'yu ($$R.3.6.1 i $$R.4.3). |to est' i v ANSI C.
Mozhno peregruzhat' imena funkcij; $$R.13.
Mozhno peregruzhat' operacii; $$R.13.4
Vozmozhna realizaciya vyzova funkcij podstanovkoj; $$R.7.1.2.
Mozhno opisyvat' ob容kty, predstavlyayushchie dannye, so specifikaciej
const; $$R.7.1.6. |to est' i v ANSI C.
Mozhno opisyvat' tipa ssylki; $$R.8.2.2 i $$R.8.4.3.
Vozmozhno upravlenie svobodnoj pamyat'yu s pomoshch'yu operacij new i
delete; $$R.5.3.3 i $$R.5.3.4.
Vvedeny klassy, kotorye pozvolyayut: skryvat' informaciyu ($$R.11),
provodit' inicializaciyu ($$R.12.1), osushchestvlyat' pol'zovatel'skie
preobrazovaniya tipa ($$R.12.3) i rabotat' s dinamicheskimi tipami
s pomoshch'yu virtual'nyh funkcij ($$R.10.2).
Imya klassa ili perechisleniya schitaetsya imenem tipa; $$R.9.
Ukazatel' na lyuboj ob容kt c tipom, ne yavlyayushchimsya const ili volatile,
mozhno prisvoit' ukazatelyu tipa void*. |to est' i v ANSI C.
Ukazatel' na funkciyu mozhno prisvaivat' ukazatelyu tipa void*;
$$R.4.6.
Opisanie vnutri bloka schitaetsya operatorom; $$R.6.7.
Mozhno opisyvat' bezymyannye ob容dineniya; $$R.9.5.
R.18.1.2 Vozmozhnosti, dobavlennye v S++ posle 1985 g.
Zdes' perechislyayutsya osnovnye rasshireniya S++ posle 1985 g.:
Klass mozhet imet' bolee odnogo pryamogo bazovogo klassa
(mnozhestvennoe nasledovanie); $$R.10.1.
CHleny klassa mogut byt' zashchishchennymi; $$R.11.
Operacii new i delete mozhno opisyvat' v klasse i peregruzhat';
$$r.5.3.3, $$R.5.3.4, $$R.12.5. |to pozvolilo opredelennyj sposob
upravleniya pamyat'yu dlya klassa s pomoshch'yu "prisvaivaniya ukazatelyu
this" otnesti v razdel anahronizmov; $$R.18.3.3.
Mozhno yavno unichtozhat' ob容kty; $$R.12.4.
Prisvaivaniya i inicializaciya dlya klassa opredeleny kak prisvaivanie i
inicializaciya po chlenam; $$R.12.8.
Sluzhebnoe slovo overload stalo izlishnim i otneseno k razdelu
anahronizmov; $$R.18.3.
Proizvol'nye vyrazheniya razresheny v kachestve inicializatorov staticheskih
ob容ktov; $$R.8.4.
Ob容kty, predstavlyayushchie dannye, mogut byt' volatile; $$R.7.1.6.
Takzhe i v ANSI C.
Dopustimy inicializatory dlya staticheskih chlenov klassa; $$R.9.4.
Funkcii-chleny mogut byt' staticheskimi; $$R.9.4.
Funkcii-chleny mogut byt' const ili volatile; $$R.9.3.1.
Mozhno yavno ukazat' svyazyvanie s podprogrammami na drugih yazykah;
$$R.7.4.
Mozhno peregruzhat' operacii ->, ->* i ` ; $$R.13.4.
Klassy mogut byt' abstraktnymi; $$R.10.3.
Dlya pol'zovatel'skih tipov prefiksnye i postfiksnye operacii
razlichayutsya.
SHablony tipov; $$R.14.
Upravlenie osobymi situaciyami; $$R.15.
Voobshche yazyk S++ obladaet bol'shimi vozmozhnostyami i nalagaet men'she
ogranichenij, chem ANSI C, poetomu bol'shinstvo konstrukcij ANSI C
yavlyayutsya zakonnymi dlya S++, prichem smysl ih ne menyaetsya. Isklyucheniya
svoditsya k sleduyushchemu:
Lyubaya programma na ANSI C, ispol'zuyushchaya v kachestve identifikatorov
sleduyushchie sluzhebnye slova S++, ne yavlyaetsya programmoj na S++; $$R.2.4:
asm catch class delete friend
inline new operator private protected
public template try this virtual
throw
Hotya eto schitaetsya ustarevshem v ANSI C, realizaciya S mozhet nalagat'
drakonovskie ogranicheniya na dlinu identifikatorov; v realizaciyah S++
eto nedopustimo; $$R.2.3.
V S++ funkciya dolzhna byt' opisana prezhde, chem ee mozhno vyzvat';
$$R.5.2.2.
Opisanie f(); v S++ oznachaet, chto funkciya f ne imeet parametrov
($$R.8.2.5), a v S eto oznachaet, chto f mozhet imet' lyuboe chislo
parametrov lyubogo tipa. Takoe opisanie schitaetsya ustarevshim v ANSI C.
V ANSI C mozhno neskol'ko raz opisat' bez specifikacii extern global'nyj
ob容kt dannyh, v S++ vozmozhno tol'ko odno ego opredelenie; $$R.3.3
V S++ klass ne mozhet imet' tozhe imya, chto i imya typedef, otnosyashcheesya
v toj zhe oblasti vidimosti k drugomu tipu; $$R.9.1.
V ANSI C operand tipa void* mozhno ispol'zovat' v pravoj chasti
prisvaivaniya, a takzhe pri inicializacii peremennoj tipa ukazatelya na
proizvol'nyj tip; v S++ eto nevozmozhno $$R.7.1.6.
V ANSI C vozmozhny komandy perehodov, obhodyashchie inicializaciyu;
v S++ eto nevozmozhno.
V ANSI C po umolchaniyu global'nyj ob容kt tipa const podlezhit
vneshnemu svyazyvaniyu; dlya S++ eto ne tak; $$R.3.3.
Opredeleniya funkcij v "starom" stile i vyzovy neopisannyh funkcij
schitayutsya v S++ anahronizmami, kotorye ne obyazatel'no dolzhny
podderzhivat'sya lyuboj realizaciej; $$R.18.3.1. V ANSI C oni prosto
schitayutsya ustarevshimi.
V S++ struktura (struct) obrazuet oblast' vidimosti ($$R.3.2);
V ANSI C struktura, perechislenie ili element perechisleniya,
opisannye v strukture podnimayutsya v oblast' vidimosti samoj
struktury.
Prisvaivanie ob容ktu tipa perechisleniya znacheniya, ne prinadlezhashchego
perechisleniyu, schitaetsya v S++ anahronizmom i ne dolzhno podderzhivat'sya
vo vseh realizaciyah; $$R.7.2. V ANSI C rekomenduetsya dlya takih
prisvaivanij vydavat' preduprezhdenie.
Stroki, inicializiruyushchie simvol'nye massivy, ne mogut byt' dlinnee
etih massivov; $$R.8.4.2.
Tip simvol'noj konstanty v S++ est' char ($$R.2.5.2) i int v
ANSI C.
Tip elementa perechisleniya est' tip etogo perechisleniya v S++ ($$R.7.2)
i tip int v ANSI C.
Krome togo, standart ANSI dlya S dopuskaet znachitel'nye razlichiya v
dopustimyh realizaciyah yazyka, chto mozhet privesti k eshche bol'shim rashozhdeniyam
mezhdu realizaciyami S++ i S. V chastnosti, v nekotoryh realizaciyah S
mogut byt' dopustimy nekotorye nesovmestimye opisaniya. V S++ trebuetsya
sovmestimost' dazhe dlya raznyh edinic translyacii; $$R.3.3.
R.18.2.1 Kak borot'sya s rashozhdeniyami
V obshchem sluchae programma na S++ ispol'zuet mnogie vozmozhnosti,
otsutstvuyushchie v ANSI C. Dlya takoj programmy neznachitel'nye rashozhdeniya,
perechislennye v $$R.18.2, yavno perekryvayutsya rasshireniyami v S++. Kogda
S++ i ANSI C dolzhny imet' obshchie zagolovochnye fajly, nuzhno pozabotit'sya,
chtoby eti fajly predstavlyali tekst na obshchem podmnozhestve etih yazykov.
Nel'zya pol'zovat'sya specificheskimi vozmozhnostyami S++ takimi, kak
klassy, peregruzka i t.p.
Nel'zya ispol'zovat' odno imya dlya oboznacheniya tipa struktury i drugogo
tipa.
Funkciyu bez parametrov sleduet opisyvat' kak f(void), a ne prosto f().
Global'nye ob容kty tipa const sleduet yavno specificirovat' kak static
ili extern.
Dlya razdeleniya chastej programmy na ANSI C i S++ mozhno ispol'zovat'
uslovnuyu translyaciyu s predopisannym imenem __cplusplus.
Funkcii, kotorye mogut vyzyvat'sya iz programm na obeih yazykah, dolzhny
byt' yavno opisany, kak funkcii, podlezhashchie svyazyvaniyu s S.
Realizaciya S++ mozhet vklyuchat' perechislennye zdes' rasshireniya, chtoby
oblegchit' ispol'zovanie programmy na S, ili chtoby uprostit' perehod
s bolee rannih versij S++. Otmetim, chto s kazhdym rasshireniem svyazany
nezhelatel'nye posledstviya. Esli realizaciya predostavlyaet takoe rasshirenie,
to ona dolzhno takzhe predostavlyat' vozmozhnost' ubedit'sya v otsutstvii
etih posledstvij dlya ishodnoj programmy. Realizaciya S++ ne obyazana
obespechivat' eti rasshireniya.
Pri opisanii ili opredelenii funkcii mozhno ispol'zovat' slovo overload
v konstrukcii specifikaciya-opisaniya ($$R.7). Esli ono ispol'zuetsya v
specifikacii-opisaniya, to schitaetsya sluzhebnym slovom i ego nel'zya
ispol'zovat' kak identifikator.
Opredelenie staticheskogo chlena klassa, predstavlyayushchego dannye,
dlya kotorogo dana standartnaya inicializaciya nulyami ($$R.8.4, $$R.9.4),
mozhet byt' opushcheno.
Mozhno ispol'zovat' komandy preprocessora starogo stilya (do ANSI C).
Mozhno prisvaivat' ob容ktu tipa perechisleniya znachenie tipa int.
Pri udalenii massiva, tip kotorogo ne imeet destruktora, mozhno
ukazyvat' chislo elementov; $$R.5.3.4.
Odna funkciya operator++() mozhet ispol'zovat'sya dlya peregruzki kak
prefiksnyh, tak i postfiksnyh operacij ++; tozhe verno dlya operacii --;
$$R.13.4.6.
R.18.3.1 Opredeleniya funkcij starogo stilya
Mozhno ispol'zovat' sintaksis S dlya opredelenij funkcij:
staroe-opredelenie-funkcii:
specifikacii-opisanij opt staryj-opisatel'-funkcii
spisok-opisanij opt telo-funkcii
staryj-opisatel'-funkcii:
opisatel' ( spisok-parametrov opt )
spisok-parametrov:
identifikator
spisok-parametrov , identifikator
Privedem primer:
max(a,b) int b; { return (a<b) ? b : a; }
Esli opredelennaya takim obrazom funkciya ne byla opisana ranee, to tip
ee formal'nyh parametrov polagaetsya (...), t.e. on ne budet proveryat'sya.
Esli ona byla opisana, to tip dolzhen soglasovyvat'sya s tipom,
ukazannym v opisanii.
Privedennyj sintaksis nel'zya ispol'zovat' dlya opredeleniya funkcij-chlenov.
R.18.3.2 Staryj stil' zadaniya inicializatora bazovogo klassa
V konstrukcii inicializator-pamyati ($$R.12.6.2) mozhno ne ukazyvat'
imya-klassa, oboznachayushchee bazovyj klass pri uslovii, chto sushchestvuet
tol'ko odin pryamoj (neposredstvennyj) bazovyj klass. Poetomu v
opisanii
class B {
// ...
public:
B(int);
};
class D : public B {
// ...
D(int i) : (i) { /* ... */ }
};
budet vyzyvat'sya konstruktor B s parametrom i.
R.18.3.3 Prisvaivanie ukazatelyu this
Prisvaivaya opredelennye znacheniya ukazatelyu this, pol'zovatel' mog
upravlyat' vydeleniem pamyati dlya ob容kta nekotorogo klassa. V
konstruktore do ispol'zovaniya chlenov klassa mozhno bylo s pomoshch'yu
takogo prisvaivaniya realizovat' svoj algoritm vydeleniya pamyati.
Prisvaivaya v destruktore ukazatelyu this nul', mozhno bylo
obojti standartnuyu operaciyu osvobozhdeniya ob容ktov klassa. Krome
togo, prisvaivanie nulya v destruktore otmenyalo neyavnye vyzovy
destruktorov dlya chlenov i bazovyh klassov, naprimer:
class Z {
int z[10];
Z() { this = my_allocator(sizeof(Z) ); }
~Z() { my_deallocator (this); this = 0; }
};
Esli vydelenie pamyati uzhe proizoshlo (kak byvaet dlya chlenov i
ob容ktov auto ili static), to pri vhode v konstruktor this imeet
nenulevoe znachenie i znachenie nul' v protivnom sluchae.
Vyzovy konstruktorov dlya chlenov i bazovyh klassov proizojdut
tol'ko posle togo, kak this poluchil znachenie. Esli v konstruktore
bazovogo klassa est' prisvaivanie this, to novoe znachenie this
budet ispol'zovat'sya i v konstruktorah proizvodnyh klassov, esli
oni est'.
Otmetim, chto pri nalichii ukazannogo anahronizma ili tip ukazatelya
this ne mozhet byt' *const, ili nuzhno delat' isklyuchenie dlya this iz
pravila o prisvaivanii ukazatelyam so specifikaciej const.
R.18.3.4 Privedenie ukazatelej na funkciyu-chlen
Ukazatel' na funkciyu-chlen nekotorogo ob容kta mozhno privesti k
ukazatelyu na kakuyu-to druguyu funkciyu, naprimer (int (*) ())p->f.
Rezul'tiruyushchij ukazatel' budet nastroen na funkciyu, vyzov kotoroj
budet proishodit' s pomoshch'yu obrashcheniya k etoj funkcii-chlenu dlya
togo zhe ob容kta. Kak obychno rezul'tat takogo vyzova schitaetsya
neopredelennym.
R.18.3.5 Nevlozhennost' klassov
Esli klass opisan vnutri drugogo klassa i v programme bol'she ne
opisano klassov s etim imenem, to ego mozhno ispol'zovat', kak
esli by on byl opisan vne klassa (tak obstoit delo s opisaniem
struct v S), naprimer:
struct S {
struct T {
int a;
};
int b;
};
struct T x; // oznachaet `S::T x;'
auto avtomaticheskij
break razryv
case variant
catch perehvatit'
char simvol
class klass
const konst
continue prodolzhit'
default po umolchaniyu
delete udalit'
do delat'
double dvojnoj
else inache
enum perechislenie
extern vneshnij
float plavayushchij
for dlya
friend drug
goto perehod na
if esli
inline podstanovka
int celyj
long dlinnyj
new novyj
operator operator
private chastnyj
protected zashchishchennyj
public obshchij
register registrovyj
return vozvrat
short korotkij
signed znakovyj
sizeof razmer
static staticheskij
struct struktura
switch pereklyuchatel'
template shablon tipa
this tekushchij
throw zapustit'
try proverit'
typedef tip
union ob容dinenie
unsigned bezznakovyj
virtual virtual'nyj
void pustoj
volatile izmenyaemyj
while poka
A
abstraktnyj
abstraktnyj klass
abstraktnyj opisatel'
abstraktnyj tip dannyh (ATD)
abstrakciya
abstrakciya dannyh
abstrakciya dannyh ili nasledovanie
avtomaticheskie
agregat
Ada
additivnye operacii
adres
adres bitovogo polya
adres i prisvaivanie
adres konstruktora
Algol68
amerikanskij nacional'nyj institut standartov (ANSI)
anahronizm
analizator rekursivnogo spuska
arifmetika bezznakovogo
arifmetika fiksirovannoj tochnosti
arifmeticheskaya osobaya situaciya
arifmeticheskie operacii s ukazatelem
arifmeticheskie preobrazovaniya
arifmeticheskij tip
assembler
asinhronnye sobytiya
associativnost' operacij
associativnyj massiv
associativnost' operacij
B
bazovyj
bazovyj klass
bezymyannoe ob容dinenie
bezznakovaya arifmetika
bezznakovaya konstanta
bezznakovyj tip
biblioteka
biblioteka zagolovochnyh fajlov
bitovoe pole
blok
blokirovanie (zamok)
buferizaciya vvoda-vyvoda
V
vvod vstroennyh tipov
vvod i vyvod
vvod pol'zovatel'skih tipov
vvod-vyvod
virtual'nyj bazovyj klass
virtual'nyj destruktor
virtual'nyj konstruktor
virtual'naya funkciya
vklyuchaemyj fajl
vklyuchenie ishodnogo fajla
vneshnee svyazyvanie
vnutrennee svyazyvanie
vnutrennyaya struktura
vlozhennyj klass
vozvrat karetki
vozvrashchaemoe funkciej znachenie
vos'merichnaya konstanta
vos'merichnoe chislo
vremya zhizni ob容kta
vstroennyj
vstroennaya operaciya
vstroennyj (osnovnoj) tip
vybor chlena klassa
vyvod vstroennyh tipov
vyvod pol'zovatel'skih tipov
vydelenie probelami
vyzov
vyzov virtual'noj funkcii
vyzov destruktora
vyzov operatornoj funkcii
vyzov po znacheniyu
vyzov po ssylke
vyzov funkcii
vyravnivanie
vyravnivanie bitovogo polya
vyravnivanie klassa
vyravnivanie chlena klassa
vyrazhenie
vyrazhenie-zapuska
vyrazhenie konstanta
vyrazhenie-konstanta
vyrazhenie-otnosheniya
vyrazhenie prisvaivaniya
vyrazhenie-privedeniya
vyrazhenie-prisvaivaniya
vyrazhenie-sdviga
vyrazhenie-razmeshcheniya
vychislenie standartnogo parametra
vychitanie ukazatelej
G
gibridnyj proekt
global'naya oblast' vidimosti
global'naya oblast' vidimosti
global'noe bezymyannoe ob容dinenie
global'noe imya
global'noe imya
global'nye dannye
global'nye ob容kty
glubokoe kopirovanie
gorizontal'naya tabulyaciya \t
gruppirovanie osobyh situacij
D
dannye
dvojnaya kavychka
desyatichnaya konstanta
destruktor
destruktor vremennogo ob容kta
destruktor lokal'nogo ob容kta
destruktor ob容dineniya
destruktor proizvodnogo klassa
dinamicheskaya inicializaciya
dinamicheskaya informaciya o tipe
dinamicheskij kontrol' tipov
dinamicheskaya oshibka
dlina imeni
dostup
dostup k bazovomu klassu
dostup k virtual'noj funkcii
dostup k zashchishchennomu chlenu
dostup k imeni chlena
dostup k chlenu bazovogo klassa
dostup k chlenu klassa
druzhestvennyj klass
druzhestvennaya funkciya
dostup k virtual'noj funkcii
E
edinica translyacii
Z
zavershenie programmy
zagolovochnyj fajl
zagruzchik
zakrytie potoka
zapros resursa
zapusk osoboj situacii
zapusk programmy
zarezervirovannyj identifikator
zashchishchennyj chlen
znakovyj tip
I
identifikator
ierarhiya klassov
ierarhiya osobyh situacij
ierarhiya ob容ktov
izmenyaemyj adres
imya
imya klassa
imya-klassa
imya peregruzhennogo chlena
imya peregruzhennoj funkcii
imya-prostogo-tipa
imya-shablonnogo-klassa
imya-funkcii-preobrazovaniya
inicializator
inicializaciya
inicializaciya avtomaticheskih
inicializaciya bazovogo klassa
inicializaciya biblioteki
inicializaciya i prisvaivanie
inicializaciya massiva
inicializaciya massiva ob容ktov klassa
inicializaciya massiva simvolov
inicializaciya ob容dineniya
inicializaciya ob容kta klassa
inicializaciya ob容kta-chlena
inicializaciya registra
inicializacii ssylki
inicializaciya struktury
inicializaciya chlena
inicializaciya chlena klassa
inkapsulyaciya
interfejs
interfejs klassa
interfejsnyj klass
ishodnyj fajl
ischerpanie svobodnoj pamyati
ischerpanie resursa
ischerpanie svobodnoj pamyati
iteraciya
K
karkas oblasti prilozheniya
klass
klass i tip
klass ili ob容dinenie
klass ili struktura
klass osoboj situacii
klass pamyati auto
Kobol
kommentarij
konec stroki \n
konkatenaciya strok
konkretnyj tip
konkretnyj tip dannyh (KTD)
konstanta
konstanta double
konstanta float
konstanta long
konstanta long double
konstanta unsigned
konstanta perechisleniya
konstanta pol'zovatel'skogo tipa
konstanta s plavayushchej tochkoj
konstanta stroka
konstruktor
konstruktor vremennogo ob容kta
konstruktor global'noj peremennoj
konstruktor i abstraktnyj klass
konstruktor kopirovaniya
konstruktor lokal'nogo ob容kta
konstruktor lokal'noj peremennoj
konstruktor ob容dineniya
konstruktor peremennoj iz svobodnoj pamyati
konstruktor proizvodnogo klassa
konstruktor chlena klassa
konstruktor chlenov massiva
kontroliruemoe ob容dinenie
kontrol' diapazona
kontrol' dostupa
kontrol' tipov parametrov funkcii
kopirovanie
kosvennost' (kosvennoe obrashchenie)
kosvennyj bazovyj klass
L
leksema
leksicheskie soglasheniya
Lisp
literal
literal'nye konstanty
logicheskaya operaciya
lokal'naya oblast' vidimosti
M
makrokomanda
makrokomanda preprocessora
makrokomanda error
makrokomanda null
makrokomanda pragma
makroobrabotka
makroopredelenie
makropodstanovka
makropodstanovka (podstanovka)
manipulyator
massiv
metka
metka case
metka default
mehanizm vyzova funkcii
metod proektirovaniya
mnogomernyj massiv
mnogosimvol'naya konstanta
mnogourovnevaya obrabotka oshibok
mnozhestvo simvolov ASCII
mnozhestvo simvolov EBCDIC
mnozhestvennoe nasledovanie
model' kaskad
modul'noe programmirovanie
modul'nost'
mul'tiplikativnoe-vyrazhenie
N
napravlennyj aciklichnyj graf
nasledovanie
nasledovanie destruktora
nasledovanie interfejsa
nasledovanie konstruktora
neodnoznachnoe preobrazovanie tipa
neodnoznachnost'
neodnoznachnost' preobrazovaniya klassa
neozhidannye osobye situacii
neopisannyj parametr
neperehvachennaya osobaya situaciya
neopredelennyj parametr konstruktora
neyavnyj vyzov destruktor
neyavnoe preobrazovanie
neyavnoe preobrazovanie tipa
neyavnoe pol'zovatel'skoe preobrazovanie
O
obobshchennyj probel
ob容dinenie
oblast' vidimosti
oblast' vidimosti friend
oblast' vidimosti vlozhennogo klassa
oblast' vidimosti imeni
oblast' vidimosti klassa
oblast' vidimosti lokal'nogo klassa
oblast' vidimosti makroimeni
oblast' vidimosti makroopredeleniya
oblast' vidimosti metki
oblast' vidimosti funkcii
oblast' vidimosti standartnogo parametra
obrabotka oshibok
obrabotchik osoboj situacii
obratnaya drobnaya cherta \
obratnyj vyzov
obshirnyj interfejs
obshchij chlen klassa
ob容kt
ob容kt-funkciya
ob容ktno-orientirovannoe programmirovanie
odinochnaya kavychka
okruzhenie programmy
operand const
operand volatile
operand ssylka
operator
operator break
operator continue
operator do
operator for
operator goto
operator if
operator return
operator switch (pereklyuchatel')
operator while
operator vyrazheniya
operator iteracii
operator opisaniya
operator perehoda
operator cikla
operator-vyrazhenie
operator-opisanie
operator-perehoda
operatornaya funkciya (operator)
operacionnaya sistema UNIX
operaciya !
operaciya #
operaciya ##
operaciya %=
operaciya &&
operaciya &=
operaciya *=
operaciya ++
operaciya +=
operaciya ,
operaciya --
operaciya -=
operaciya /=
operaciya ::
operaciya <<=
operaciya >>=
operaciya ^=
operaciya bol'she ili ravno
operaciya bol'she chem
operaciya vvoda >>
operaciya vzyatiya adresa
operaciya vybora chlena klassa
operaciya vyvoda <<
operaciya vyzova funkcii
operaciya dekrement
operaciya zapyataya
operaciya indeksacii
operaciya inkrement
operaciya kosvennosti
operaciya logicheskogo otricaniya
operaciya logicheskoe I
operaciya logicheskoe ILI
operaciya men'she ili ravno
operaciya men'she chem
operaciya neravno
operaciya otnosheniya
operaciya preobrazovaniya
operaciya privedeniya
operaciya ravenstva
operaciya prisvaivaniya
operaciya-prisvaivaniya
operaciya razresheniya oblasti vidimosti
operaciya sdviga vlevo
operaciya slozheniya
operaciya usloviya ( ? : )
operaciya umnozheniya
operaciya unarnyj minus
operaciya delete
operaciya new
operaciya sizeof
opisanie
opisanie asm
opisanie extern
opisanie friend
opisanie register
opisanie typedef
opisanie bitovogo polya
opisanie v kachestve opredeleniya
opisanie vneshnih
opisanie vlozhennogo klassa
opisanie dostupa
opisanie druzhestvennogo klassa
opisanie ili opredelenie
opisanie imeni
opisanie imeni klassa
opisanie klassa
opisanie klassa pamyati
opisanie lokal'nogo klassa
opisanie massiva
opisanie parametra
opisanie postoyannogo ukazatelya
opisanie ssylki
opisanie staticheskogo chlena
opisanie standartnogo parametra
opisanie staticheskogo chlena
opisanie tipa
opisanie ukazatelya
opisanie funkcii
opisanie funkcii-chlena
opisanie chlena
opisanie chlena klassa
opisanie shablona tipa
opisanie-shablona-tipa
opisanie shablonnogo klassa
opisanie shablonnoj funkcii
opisanie ellipsisa v funkcii
opisanie-osoboj-situacii
opisanie-parametra
opisatel'
opisatel'-chlena
opredelenie
opredelenie virtual'noj funkcii
opredelenie klassa
opredelenie konstruktora
opredelenie oblasti vidimosti funkcii
opredelenie ob容kta
opredelenie staticheskogo chlena
opredelenie funkcii
opredelenie-funkcii
opredelenie funkcii-chlena
opredelenie funkcii-chlena inline
opredelenie shablonnogo klassa
opredelenie shablonnoj funkcii
opredelenie chisto virtual'noj funkcii
opredelenie chlena
opredelenie shablonnogo klassa
opredelenie shablonnoj funkcii
opredelenie elementa perechisleniya
osobaya situaciya
osvobozhdenie resursa
osnovnoj tip
otladka
otlichiya ot vychisleniya vyrazhenij v S
otlichiya ot oblasti vidimosti S
otlichiya ot opisaniya funkcii v S
otlichiya ot prostranstva imenovaniya S
otlichiya ot svyazyvaniya v S
oshibka svyazyvaniya
P
pamyat' dlya klassa
pamyat' dlya massiva
paradigma programmirovaniya
parametr
parametry komandnoj stroki
parametr funkcii
param-shablona-tipa
parametr-shablona-tipa
pervichnoe vyrazhenie
perevod formata \f
peregruzka
peregruzka binarnoj operacii
peregruzka dekrementa
peregruzka i dostup
peregruzka i oblast' vidimosti
peregruzka i ssylka
peregruzka imeni funkcii
peregruzka imeni chlena
peregruzka indeksacii
peregruzka inkrementa
peregruzka operacii
peregruzka operacii vybora chlena
peregruzka operacii vyzova
peregruzka operacii prisvaivaniya
peregruzka unarnoj operacii
peredacha parametra funkcii
pereopredelenie virtual'noj funkcii
perepolnenie
perehvatit' (osobuyu situaciyu)
perechislenie
pobochnye effekty
poverhnostnoe kopirovanie
povtornyj zapusk (osoboj situacii)
podderzhka abstrakcii dannyh
podderzhka ob容ktno-orientirovannogo programmirovaniya
pole
polnoe-imya-klassa
pol'zovatel'skaya operaciya
pol'zovatel'skaya operaciya *=
pol'zovatel'skaya operaciya +
pol'zovatel'skaya operaciya ++
pol'zovatel'skaya operaciya -
pol'zovatel'skaya operaciya --
pol'zovatel'skaya operaciya ->
pol'zovatel'skaya operaciya =
pol'zovatel'skaya operaciya indeksacii
pol'zovatel'skij tip
pol'zovatel'skoe preobrazovanie
pol'zovatel'skaya unarnaya operaciya
pomechennyj operator
porazryadnyj
porazryadnoe I
porazryadnoe vklyuchayushchee ILI
porazryadnoe isklyuchayushchee ILI
porazryadnoe kopirovanie
porazryadnye operacii
porazryadnye logicheskie operacii
poryadok vypolneniya operacij
poryadok vychislenij
poryadok vychisleniya vyrazheniya
poryadok vychisleniya parametrov
posledovatel'nost' razryadov
postoyannoe vyrazhenie
postfiksnoe vyrazhenie
postfiksnye ++ i --
pravila razresheniya peregruzki
pravila oblastej vidimosti
pravila preobrazovaniya tipa
predvaritel'noe opisanie
predvaritel'noe opisanie klassa
predvaritel'noe opisanie shablona tipa
predopredelennaya operaciya vzyatiya adresa
predopredelennoe prisvaivanie
predopredelennye makroimena
preobrazovanie (tipa)
preobrazovanie adresa
preobrazovanie klassa (tipa)
preobrazovanie nulevogo ukazatelya
preobrazovanie ob容kta klassa
preobrazovanie odnogo ukazatelya v drugoj
preobrazovanie parametra
preobrazovanie plavayushchej tochki v celoe
preobrazovanie pol'zovatel'skogo tipa
preobrazovanie pri prisvaivanii
preobrazovanie pustogo ukazatelya
preobrazovanie s pomoshch'yu konstruktora
preobrazovanie ssylki
preobrazovanie tipa vozvrashchaemogo znacheniya
preobrazovaniya tipa parametra funkcii
preobrazovanie ukazatelya
preobrazovanie ukazatelya bazovogo klassa
preobrazovanie ukazatelya v klass
preobrazovanie ukazatelya v funkciyu
preobrazovanie ukazatelya v celoe
preobrazovanie ukazatelya v chlen
preobrazovanie ukazatelya na massiv
preobrazovanie ukazatelya na proizvodnyj klass
preobrazovanie ukazatelya tipa void*
preobrazovanie celogo
preobrazovanie celogo v ukazatel'
prefiksnye ++ i --
privedenie
privedenie adresa
privedenie bazovogo klassa
privedenie ob容kta klassa
privedenie proizvodnogo klassa
privedenie k bazovomu klassu
privedenie odnogo ukazatelya v drugoj
privedenie ssylki
privedenie ukazatelya k funkcii
privedenie ukazatelya k celomu
privedenie ukazatelya k chlenu
privedenie celogo k ukazatelyu
prinadlezhnost'
prinadlezhnost' i nasledovanie
prioritet operacij
prisvaivanie
prisvaivanie i adres
prisvaivanie i inicializaciya
prisvaivanie ssylke
prisvaivanie ukazatelyu
proveryaemyj-blok
proverka tipa standartnogo parametra
programma
programmirovanie
proektirovanie S++
proektirovanie biblioteki
proektirovanie i klassy
proektirovanie i programmirovanie
proektirovanie i yazyk
proektirovanie servisnyh programm
proizvodnyj klass
prototipy
procedurnoe programmirovanie
process razvitiya
pryamoj bazovyj klass
pustaya ochered'
pustoj operator
pustoj spisok parametrov
pustoj parametr
pustoj ukazatel' (NULL)
R
razbienie osobyh situacij
razbienie programmy
razvitie S++
razdel'naya translyaciya
razmer massiva po umolchaniyu
razmer stroki
razmer struktury
razmer ukazatelya
razmeshchenie
razmnozhenie znaka
razmeshchenie bitovogo polya
razreshenie neodnoznachnosti
razreshenie peregruzki
razreshenie peregruzki shablonnoj
razryad (bit)
razryadnyj vektor
raskruchivanie steka
raspolozhenie bitovyh polej
raspolozhenie ob容ktov klassa
realizaciya
redaktor svyazej
rekursivnyj vyzov funkcii
rekursiya
S
sborka musora
svobodnaya pamyat'
svodka makrokomand
svodka operatorov
svodka operacij
svodka pravil oblasti vidimosti
svodka sintaksisa vyrazheniya
svyazyvanie
svyazyvanie vneshnih
svyazyvanie lokal'nogo imeni
svyazyvanie staticheskih
svyazyvanie shablona tipa
simvol
simvol shag nazad
simvol'naya konstanta
simvol NULL '\0'
simvol podcherkivaniya _
Simula
sintaksis makroopredelenij (svodka)
sintaksis operatorov
sintaksis vyrazhenij
sintaksis makrokomand
sintaksis operatorov
sintaksis opisanij
sintaksis opisanij klassa
sintaksis opisatelej
sintaksis osobyh situacij
sintaksis shablona tipa
slozhnoe imya klassa
sluzhebnoe slovo
sluzhebnoe slovo class
sovmestimost'
sovmestimost' s ANSI C (svodka)
sovmestimost' s S (svodka)
soglasovannoe svyazyvanie
soprovozhdenie programm
sostavnoj operator
sostoyanie potoka
special'nyj simvol
specifikacii interfejsa
specifikaciya auto
specifikaciya vneshnego svyazyvaniya
specifikaciya dostupa
specifikaciya opisaniya
specifikaciya-bazovyh
specifikaciya-klassa
specifikaciya klassa pamyati
specifikaciya-osoboj-situacii
specifikaciya-opisatelya
specifikaciya-svyazi
specifikaciya svyazi funkcii
specifikaciya-tipa
specifikaciya tipa double
specifikaciya-tipa-char
specifikaciya tipa enum
specifikaciya tipa float
specifikaciya tipa int
specifikaciya tipa short
specifikaciya tipa struct
specifikaciya tipa union
specifikaciya tipa unsigned
specifikaciya tipa void
specifikaciya tipa volatile
specifikaciya funkcii
specifikaciya shablona tipa
specifikaciya friend
specifikaciya inline
specifikaciya pure
specifikaciya-pure
specifikaciya static
specifikaciya typedef
specifikaciya template
specifikaciya virtual
spisok-bazovyh
spisok-vyrazhenij
spisok-inicializatorov
spisok-obrabotchikov
spisok operatornyh funkcij
spisok-opisanij
spisok-opisatelej
spisok-param-shablona-tipa
spisok-parametrov-shablona-tipa
spisok sluzhebnyh slov
spisok-chlenov
sravnenie ukazatelej
sredstva proektirovaniya
ssylka
ssylka const
ssylka volatile
ssylochnoe vyrazhenie
stadii proektirovaniya
stadii razvitiya
stadii translyacii
standartnye biblioteki
standartnyj destruktor
standartnye zagolovochnye fajly
standartnaya inicializaciya
standartnyj katalog include
standartnyj katalog vklyuchaemyh fajlov
standartnyj komponent
standartnyj konstruktor
standartnyj konstruktor kopirovaniya
standartnyj kontrol' dostupa
standartnaya operaciya prisvaivaniya
standartnyj parametr
standartnoe preobrazovanie
standartnoe celochislennoe preobrazovanie
staticheskaya funkciya-chlen
staticheskij klass pamyati
staticheskij kontrol' tipov
staticheskij lokal'nyj ob容kt
staticheskij chlen
staticheskij chlen klassa
stroka formata
strokovyj klass
strokovyj potok
struktura
struktura bloka
T
telo funkcii
tip
tip bitovogo polya
tip vozvrashchaemogo znacheniya
tip virtual'noj funkcii
tip konstruktora
tip massiva
tip stroki
tip ukazatelya
tip funkcii
tip char
tip double
tip float
tip int
tip long
tip long double
tip short
tip signed char
tip unsigned char
tip void
tip volatile
tochka zapuska
trigraf
U
uzlovoj klass
ukazanie razmeshcheniya
ukazatel'
ukazatel' na klass
ukazatel' na funkciyu
ukazatel' na funkciyu-chlen
ukazatel' tipa void*
ukazatel' const
unarnoe vyrazhenie
unarnaya operaciya
unarnaya-operaciya
unarnoe vyrazhenie
unarnoe-vyrazhenie
unichtozhenie
unichtozhenie avtomaticheskih
unichtozhenie lokal'noj peremennoj
unichtozhenie lokal'nyh staticheskih
upravlenie
upravlenie pamyat'yu
upravlenie svobodnoj pamyat'yu
upravlyayushchij klass
upravlyayushchaya posledovatel'nost'
upravlyayushchij simvol (\)
upryatyvanie imeni
urovni abstrakcii
uslovnaya translyaciya
uslovnyj
utochnennoe imya
utochnennoe-imya
utochnennoe-imya-klassa
utochnennoe-imya-tipa
F
fajl i potok
fajlovaya oblast' vidimosti
formatirovannyj vyvod
funkciya
funkcional'naya makrokomanda
funkciya-podstanovka
funkciya-chlen
funkciya-chlen klassa
funkciya-chlen friend
funkciya-chlen inline (podstanovka)
funkciya-chlen lokal'nogo klassa
funkciya-chlen volatile
funkciya-chlen ob容dineniya
C
celaya konstanta
celi proektirovaniya
celochislennoe preobrazovanie
celochislennyj tip
cikl razvitiya
CH
chastnyj bazovyj klass
chastnyj chlen klassa
chlen
chlen klassa
chlen proizvodnogo klassa
chisto virtual'naya funkciya
SH
shablon tipa
shablonnyj klass
shablonnaya funkciya
shablonnaya funkciya-chlen
shagi proektirovaniya
shestnadcaterichnaya konstanta
shirokosimvol'naya stroka
|
ekvivalentnost' tipov
ekvivalentnost' shablonnyh tipov
element perechisleniya
ellipsis ...
YA
yavnoe preobrazovanie tipa
yavnyj vyzov destruktora
yavnyj vyzov konstruktora
yazyk
yazyk vysokogo urovnya
yazyk nizkogo urovnya
yazyk BCPL
yazyk C++
yazyk CLU
yazyk SMALLTALK
yazyki C i C++
A
abstract abstraktnyj
class abstraktnyj klass
abstract-declarator abstraktnyj opisatel'
abstraction abstrakciya
data abstrakciya dannyh
levels urovni abstrakcii
access dostup
base class dostup k bazovomu klassu
base class member dostup k chlenu bazovogo klassa
class member dostup k chlenu klassa
control kontrol' dostupa
declaration opisanie dostupa
member name dostup k imeni chlena
protected member dostup k zashchishchennomu chlenu
specifier specifikaciya dostupa
virtual function dostup k virtual'noj funkcii
Ada Ada
addition operator operaciya slozheniya
additive operators additivnye operacii
address adres
address-of operator operaciya vzyatiya adresa
ADT abstract type abstraktnyj tip dannyh (ATD)
aggregate agregat
Algol68 Algol68
alignmemt vyravnivanie
allocation razmeshchenie
allocation-expression vyrazhenie-razmeshcheniya
ambiguity neodnoznachnost'
resolution razreshenie neodnoznachnosti
ambiguous type conversion neodnoznachnoe preobrazovanie tipa
anachronism anahronizm
anonymous union bezymyannoe ob容dinenie
ANSI ANSI
application framework karkas oblasti prilozheniya
argument parametr
argument-declaration opisanie-parametra
arithmetic arifmeticheskij
conversion arifmeticheskoe preobrazovanie
exception arifmeticheskaya osobaya situaciya
fixed point arifmetika fiksirovannoj tochnosti
pointer arifmeticheskie operacii s ukazatelem
type arifmeticheskij tip
unsigned arifmetika bezznakovogo
array massiv
associative associativnyj massiv
initialization inicializaciya massiva
multidimensional mnogomernyj massiv
storage of pamyat' dlya massiva
type tip massiva
arrow operator vybor chlena klassa
ASCII character set mnozhestvo simvolov ASCII
asm declaration opisanie asm
assembler assembler
assignment prisvaivanie
and initialization prisvaivanie i inicializaciya
and lvalue prisvaivanie i adres
assignment-expression vyrazhenie-prisvaivaniya
assignment-operator operaciya-prisvaivaniya
associativity of operator associativnost' operacij
asynchronous events asinhronnye sobytiya
auto avtomaticheskie
destruction unichtozhenie avtomaticheskih
initialization inicializaciya avtomaticheskih
specifier specifikaciya auto
storage class klass pamyati auto
B
backslash obratnaya drobnaya cherta
backspace simvol shag nazad
base bazovyj
class bazovyj klass
class access dostup k bazovomu klassu
class cast privedenie k bazovomu klassu
base-list spisok-bazovyh
base-specifier specifikaciya-bazovyh
BCPL BCPL
binding svyazyvanie
bit razryad (bit)
field bitovoe pole
pattern posledovatel'nost' razryadov
vector razryadnyj vektor
bit-field bitovoe pole
address of adres bitovogo polya
alignment vyravnivanie bitovogo polya
declaration opisanie bitovogo polya
layout razmeshchenie bitovogo polya
type tip bitovogo polya
bitwise porazryadnyj
AND operator porazryadnoe I
copy porazryadnoe kopirovanie
exclusive OR operator porazryadnoe isklyuchayushchee ILI
inclusive OR operator porazryadnoe vklyuchayushchee ILI
logical operators logicheskie operacii
operators porazryadnye operacii
block blok
statement { } sostavnoj operator
structure struktura bloka
body, function telo funkcii
break statement operator break
buffering, I/O buferizaciya vvoda-vyvoda
built-in vstroennyj
operator vstroennaya operaciya
type vstroennyj (osnovnoj) tip
C
C C
C ANSI C ANSI
C++ C i C++
C++ C++
evolution razvitie C++
call vyzov
by reference vyzov po ssylke
by value vyzov po znacheniyu
function vyzov funkcii
operator function vyzov operatornoj funkcii
callback obratnyj vyzov
carriage return vozvrat karetki
cast privedenie
base class privedenie bazovogo klassa
class object privedenie ob容kta klassa
derived class privedenie proizvodnogo klassa
integer to pointer privedenie celogo k ukazatelyu
operator operaciya privedeniya
pointer to function privedenie ukazatelya k funkcii
pointer to integer privedenie ukazatelya k celomu
pointer to member privedenie ukazatelya k chlenu
pointer to pointer privedenie odnogo ukazatelya
v drugoj
reference privedenie ssylki
cast-expression vyrazhenie-privedeniya
catch perehvatit'
CDT concrete type konkretnyj tip dannyh (KTD)
char type tip char
type, signed tip signed char
type specifier specifikaciya-tipa-char
type, unsigned tip unsigned char
character simvol
constant simvol'naya konstanta
set, ASCII mnozhestvo simvolov ASCII
set, EBCDIC mnozhestvo simvolov EBCDIC
class klass
abstract abstraktnyj klass
alignment vyravnivanie klassa
and type klass i tip
base bazovyj klass
constructor and abstract konstruktor i abstraktnyj klass
constructor for derived konstruktor dlya proizvodnogo klassa
conversion preobrazovanie ob容kta klassa
conversion ambiguity neodnoznachnost' preobrazovaniya
ob容kta klassa
declaration opisanie klassa
declaration, forward predvaritel'noe opisanie klassa
declaration, friend opisanie druzhestvennogo klassa
definition opredelenie klassa
derived proizvodnyj klass
destructor for derived destruktor proizvodnogo klassa
exception klass osoboj situacii
friend druzhestvennyj klass
handle upravlyayushchij klass
hierarchy ierarhiya klassov
interface interfejs klassa
member chlen klassa
member access dostup k chlenu klassa
member access operator operaciya vybora chlena klassa
member, alignment vyravnivanie chlena klassa
member, constructor for konstruktor chlena klassa
member declaration opisanie chlena klassa
member function funkciya-chlen klassa
member initialization inicializaciya chlena klassa
member of derived chlen proizvodnogo klassa
member, private chastnyj chlen klassa
member, public obshchij chlen klassa
member, static staticheskij chlen klassa
name imya klassa
name declaration opisanie imeni klassa
name, elaborated slozhnoe imya klassa
nested vlozhennyj klass
node uzlovoj klass
pointer to ukazatel' na klass
private base chastnyj bazovyj klass
scope oblast' vidimosti klassa
storage pamyat' dlya klassa
template shablonnyj klass
versus struct klass ili struktura
versus union klass ili ob容dinenie
virtual base virtual'nyj bazovyj klass
class-key sluzhebnoe slovo class
class-name imya-klassa
class-specifier specifikaciya-klassa
CLU CLU
Cobol Kobol
comma operator operaciya zapyataya
command line argument parametry komandnoj stroki
comment kommentarij
compatibility sovmestimost'
with ANSI C summary sovmestimost' s ANSI C (svodka)
with C summary sovmestimost' s S (svodka)
compilation, separate razdel'naya translyaciya
complete-class-name polnoe-imya-klassa
compound statement sostavnoj operator
concatenation string konkatenaciya strok
concrete type konkretnyj tip
type, CDT konkretnyj tip dannyh (KTD)
conditional uslovnyj
compilation uslovnaya translyaciya
expression operator operaciya usloviya ( ? : )
constant konstanta
character simvol'naya konstanta
decimal desyatichnaya konstanta
double konstanta double
enumeration konstanta perechisleniya
expression vyrazhenie konstanta
float konstanta float
floating point konstanta s plavayushchej tochkoj
hexadecimal shestnadcaterichnaya konstanta
integer celaya konstanta
long konstanta long
long double konstanta long double
multicharacter mnogosimvol'naya konstanta
octal vos'merichnaya konstanta
of user-defined type konstanta pol'zovatel'skogo tipa
unsigned konstanta unsigned
constant-expression vyrazhenie-konstanta
constructor konstruktor
address of adres konstruktora
call, explicit yavnyj vyzov konstruktora
conversion by preobrazovanie s pomoshch'yu
konstruktora
copy konstruktor kopirovaniya
default standartnyj konstruktor
default copy standartnyj konstruktor kopirovaniya
definition opredelenie konstruktora
exception handling konstruktor v obrabotke
osobyh situacij
for array members konstruktor chlenov massiva
for class member konstruktor chlena klassa
for derived class konstruktor proizvodnogo klassa
for free store variable konstruktor peremennoj,
razmeshchaemoj v svobodnoj pamyati
for global variable konstruktor global'noj peremennoj
for local variable konstruktor lokal'noj peremennoj
for temporary konstruktor vremennogo ob容kta
inheritance nasledovanie konstruktorov
local object konstruktor lokal'nogo ob容kta
type of tip konstruktora
undefined argument to neopredelennyj parametr konstruktora
union konstruktor ob容dineniya
virtual virtual'nyj konstruktor
containment prinadlezhnost'
and inheritance prinadlezhnost' i nasledovanie
continue statement operator continue
control access kontrol' dostupa
conversion preobrazovanie (tipa)
argument preobrazovanie parametra
arithmetic arifmeticheskie preobrazovaniya
array pointer preobrazovanie ukazatelya na massiv
base class pointer preobrazovanie ukazatelya
bazovogo klassa
by assignment preobrazovanie pri prisvaivanii
by constructor preobrazovanie konstruktorom
class preobrazovanie klassa (tipa)
derived class pointer preobrazovanie ukazatelya
na proizvodnogo klassa
floating point integer preobrazovanie znacheniya s
plavayushchej tochkoj v celoe
implicit neyavnoe preobrazovanie
implicit type neyavnoe preobrazovanie tipa
integer preobrazovanie celogo
integer to pointer preobrazovanie celogo v ukazatel'
lvalue preobrazovanie adresa
null pointer preobrazovanie pustogo ukazatelya
of pointer to class preobrazovanie ukazatelya v klass
operator operaciya preobrazovaniya
pointer preobrazovanie ukazatelya
pointer to function preobrazovanie ukazatelya v funkciyu
pointer to integer preobrazovanie ukazatelya v celoe
pointer to member preobrazovanie ukazatelya v chlen
pointer to pointer preobrazovanie odnogo ukazatelya
v drugoj
reference preobrazovanie ssylki
return type preobrazovanie tipa vozvrashchaemogo
znacheniya
rules, type pravila preobrazovaniya tipa
standard standartnoe preobrazovanie
user-defined pol'zovatel'skoe preobrazovanie
user-defined type preobrazovanie pol'zovatel'skogo tipa
void* pointer preobrazovanie ukazatelya tipa void*
zero pointer preobrazovanie nulevogo ukazatelya
conversion-function-name imya-funkcii-preobrazovaniya
copy kopirovanie
bitwise porazryadnoe kopirovanie
deep glubokoe kopirovanie
shallow poverhnostnoe kopirovanie
D
data dannye
abstraction abstrakciya dannyh
abstraction, support for podderzhka abstrakcii dannyh
abstraction vs inheritance abstrakciya dannyh ili nasledovanie
global global'nye dannye
debugging otladka
declaration opisanie
access opisanie dostupa
argument opisanie parametra
array opisanie massiva
as definition opisanie v kachestve opredeleniya
asm opisanie asm
bit-field opisanie bitovogo polya
class opisanie klassa
class member opisanie chlena klassa
class name opisanie imeni klassa
constant pointer opisanie postoyannogo ukazatelya
default argument opisanie standartnogo parametra
definition versus opisanie ili opredelenie
ellipsis in function opisanie ellipsisa v funkcii
extern opisanie extern
forward predvaritel'noe opisanie
friend opisanie friend
friend class opisanie druzhestvennogo klassa
function opisanie funkcii
function member opisanie funkcii-chlena
function template opisanie shablonnoj funkcii
local class opisanie lokal'nogo klassa
member opisanie chlena
name opisanie imeni
pointer opisanie ukazatelya
reference opisanie ssylki
register opisanie register
specifier specifikaciya opisaniya
statement operator opisaniya
static member opisanie staticheskogo chlena
storage class opisanie klassa pamyati
syntax summary sintaksis opisanij (svodka)
syntax summary, class sintaksis opisanij klassa (svodka)
template opisanie shablona tipa
template class opisanie shablonnogo klassa
template function opisanie shablonnoj funkcii
type opisanie tipa
typedef opisanie typedef
declaration opisanie
declaration-list spisok-opisanij
declaration-statement operator-opisanie
declarator opisatel'
declarator-list spisok-opisatelej
decl-specifier specifikaciya-opisatelya
decrement operator operaciya dekrement
default access control standartnyj kontrol' dostupa
argument standartnyj parametr
argument evaluation vychislenie standartnogo parametra
argument, scope oblast' vidimosti standartnogo parametra
argument type checking proverka tipa standartnogo parametra
array size razmer massiva po umolchaniyu
assignment operator standartnaya operaciya prisvaivaniya
constructor standartnyj konstruktor
copy constructor standartnyj konstruktor kopirovaniya
destructor standartnyj destruktor
initialization standartnaya inicializaciya
definition opredelenie
class opredelenie klassa
constructor opredelenie konstruktora
enumerator opredelenie elementa perechisleniya
function opredelenie funkcii
function template opredelenie shablonnoj funkcii
inline member function opredelenie funkcii-chlena inline
member opredelenie chlena
member function opredelenie funkcii-chlena
object opredelenie ob容kta
pure virtual function opredelenie chisto virtual'noj
funkcii
scope of function opredelenie oblasti vidimosti
funkcii
static member opredelenie staticheskogo chlena
template class opredelenie shablonnogo klassa
template function opredelenie shablonnoj funkcii
virtual function opredelenie virtual'noj funkcii
delete operator operaciya delete
dereferencing kosvennost' (kosvennoe obrashchenie)
derived class proizvodnyj klass
design aims celi proektirovaniya
and classes proektirovanie i klassy
and language proektirovanie i yazyk
and programming proektirovanie i programmirovanie
library proektirovanie biblioteki
method metod proektirovaniya
of C++ proektirovanie S++
stage stadii proektirovaniya
steps shagi proektirovaniya
tools sredstva proektirovaniya
destruction unichtozhenie
of auto unichtozhenie avtomaticheskih
of local static unichtozhenie lokal'nyh staticheskih
of local variable unichtozhenie lokal'noj peremennoj
destructor destruktor
default standartnyj destruktor
for derived class destruktor proizvodnogo klassa
for temporary destruktor vremennogo ob容kta
inheritance nasledovanie destruktora
invocation vyzov destruktora
local object destruktor lokal'nogo ob容kta
virtual virtual'nyj destruktor
development cycle cikl razvitiya
process process razvitiya
stages stadii razvitiya
difference from C expression otlichiya ot vychisleniya vyrazhenij v S
evaluation
from C function declaration otlichiya ot opisaniya funkcii v S
from C linkage otlichiya ot svyazyvaniya v S
from C name space otlichiya ot prostranstva imenovaniya S
from C scope otlichiya ot oblasti vidimosti S
direct base class pryamoj bazovyj klass
directed acyclic graph napravlennyj aciklichnyj graf
directive error preprocessing makrokomanda error
pragma preprocessing makrokomanda pragma
preprocessing makrokomanda preprocessora
discriminating union kontroliruemoe ob容dinenie
discrimination of exceptions razbienie osobyh situacij
do statement operator do
double constant konstanta double
type tip double
type specifier specifikaciya tipa double
dynamic type checking dinamicheskij kontrol' tipov
E
EBCDIC character set mnozhestvo simvolov EBCDIC
elaborated class name slozhnoe imya klassa
ellipsis ... ellipsis ...
empty argument list pustoj spisok parametrov
queue pustaya ochered'
statement pustoj operator
encapsulation inkapsulyaciya
enum type specifier specifikaciya tipa enum
enumeration perechislenie
constant konstanta perechisleniya
enumerator element perechisleniya
equality operator operaciya ravenstva
equivalence template type ekvivalentnost' shablonnyh tipov
type ekvivalentnost' tipov
error handling obrabotka oshibok
handling, multilevel mnogourovnevaya obrabotka oshibok
linkage oshibka svyazyvaniya
preprocessing directive makrokomanda error
run-time dinamicheskaya oshibka
escape character upravlyayushchij simvol (\)
sequence upravlyayushchaya posledovatel'nost'
evaluation default argument vychislenie standartnogo parametra
of expression, order of poryadok vychisleniya vyrazheniya
order of poryadok vychislenij
order of argument poryadok vychisleniya parametrov
evolution of S++ razvitie S++
exception osobaya situaciya
arithmetic arifmeticheskaya osobaya situaciya
class klass osoboj situacii
handler obrabotchik osoboj situacii
hierarchies ierarhiya osobyh situacij
throwing zapusk osoboj situacii
exception-declaration opisanie-osoboj-situacii
exception-specification specifikaciya-osoboj-situacii
exhaustion free store ischerpanie svobodnoj pamyati
explicit constructor call yavnyj vyzov konstruktora
destructor call yavnyj vyzov destruktora
type conversion yavnoe preobrazovanie tipa
expression vyrazhenie
assignment vyrazhenie prisvaivaniya
constant postoyannoe vyrazhenie
order of evaluation of poryadok vychisleniya vyrazheniya
postfix postfiksnoe vyrazhenie
primary pervichnoe vyrazhenie
reference ssylochnoe vyrazhenie
statement operator vyrazhenie
syntax summary svodka sintaksisa vyrazheniya
unary unarnoe vyrazhenie
expression-list spisok-vyrazhenij
expression-statement operator-vyrazhenie
extern declaration opisanie vneshnih
linkage svyazyvanie vneshnih
linkage specification specifikaciya vneshnego svyazyvaniya
external linkage vneshnee svyazyvanie
F
fat interface obshirnyj interfejs
field pole
bit bitovoe pole
fixed point arithmetic arifmetika s fiksirovannoj tochnost'yu
float constant konstanta float
type tip float
type specifier specifikaciya tipa float
for statement operator for
format string stroka formata
form feed \f perevod formata \f
forward class declaration predvaritel'noe opisanie klassa
declaration predvaritel'noe opisanie
declaration of template predvaritel'noe opisanie shablona tipa
free store svobodnaya pamyat'
store exhaustion ischerpanie svobodnoj pamyati
store management upravlenie svobodnoj pamyat'yu
friend friend
class druzhestvennyj klass
declaration opisanie friend
function druzhestvennaya funkciya
member function funkciya-chlen friend
scope of oblast' vidimosti friend
specifier specifikaciya friend
function funkciya
argument parametr funkcii
argument passing peredacha parametra funkcii
argument type checking kontrol' tipov parametrov funkcii
argument type conversion preobrazovaniya tipa parametra
funkcii
body telo funkcii
call vyzov funkcii
call mechanism mehanizm vyzova funkcii
call, recursive rekursivnyj vyzov funkcii
declaration opisanie funkcii
definition opredelenie funkcii
friend druzhestvennaya funkciya
inline funkciya-podstanovka
inline member funkciya-chlen inline (podstanovka)
linkage specification specifikaciya svyazi funkcii
member funkciya-chlen
object ob容kt-funkciya
operator operatornaya funkciya (operator)
pointer to ukazatel' na funkciyu
pointer to member ukazatel' na funkciyu-chlen
pure virtual chisto virtual'naya funkciya
scope oblast' vidimosti funkcii
specifier specifikaciya funkcii
template shablonnaya funkciya
type tip funkcii
value return vozvrashchaemoe funkciej znachenie
virtual virtual'naya funkciya
function-definition opredelenie-funkcii
fundamental type osnovnoj tip
G
garbage collection sborka musora
global anonymous union global'noe bezymyannoe ob容dinenie
data global'nye dannye
name global'noe imya
objects global'nye ob容kty
scope global'naya oblast' vidimosti
goto statement operator goto
greater than operator operaciya bol'she chem
greater than or equal operator operaciya bol'she ili ravno
grouping of exceptions gruppirovanie osobyh situacij
H
handle class upravlyayushchij klass
handler, exception obrabotchik osoboj situacii
handler-list spisok-obrabotchikov
header file zagolovochnyj fajl
hexadecimal constant shestnadcaterichnaya konstanta
hierarchy class ierarhiya klassov
object ierarhiya ob容ktov
horizontal tab \t gorizontal'naya tabulyaciya \t
hybrid design gibridnyj proekt
I
identifier identifikator
if statement operator if
implementation realizaciya
implicit conversion neyavnoe preobrazovanie
destructor call neyavnyj vyzov destruktor
type conversion neyavnoe preobrazovanie tipa
user-defined conversion neyavnoe pol'zovatel'skoe
preobrazovanie
include directory, standard standartnyj katalog include
file vklyuchaemyj fajl
inclusion source file vklyuchenie ishodnogo fajla
increment operator operaciya inkrement
indentation vydelenie probelami
inderect base class kosvennyj bazovyj klass
inderection operator operaciya kosvennosti
inequality operator operaciya neravno
inheritance nasledovanie
containment and prinadlezhnost' i nasledovanie
multiple mnozhestvennoe nasledovanie
of constructor nasledovanie konstruktora
of destructor nasledovanie destruktora
initialization inicializaciya
array inicializaciya massiva
array of class objects inicializaciya massiva ob容ktov klassa
assignment and inicializaciya i prisvaivanie
character array inicializaciya massiva simvolov
class member inicializaciya chlena klassa
class object inicializaciya ob容kta klassa
default standartnaya inicializaciya
dynamic dinamicheskaya inicializaciya
member inicializaciya chlena
member object inicializaciya ob容kta-chlena
of base class inicializaciya bazovogo klassa
of structure inicializaciya struktury
initializer inicializator
initializer-list spisok-inicializatorov
inline inline
function funkciya-podstanovka
member function funkciya-chlen inline
input and output vvod-vyvod
of built-in type vvod vstroennyh tipov
of user-defined type vvod pol'zovatel'skih tipov
operator >> operaciya vvoda >>
int int
type tip int
type specifier specifikaciya tipa int
integer constant celaya konstanta
conversion celochislennoe preobrazovanie
integral promotion standartnoe celochislennoe
preobrazovanie
type celochislennyj tip
interface interfejs
class interfejsnyj klass
inheritance nasledovanie interfejsa
fat obshirnyj interfejs
specifications specifikacii interfejsa
internal linkage vnutrennee svyazyvanie
structure vnutrennyaya struktura
I/O buffering buferizaciya vvoda-vyvoda
iteration iteraciya
statement operator iteracii
J
jump statement operator perehoda
jump-statement operator-perehoda
K
keyword sluzhebnoe slovo
list spisok sluzhebnyh slov
L
label metka
case metka case
default metka default
scope of oblast' vidimosti metki
labeled statement pomechennyj operator
language yazyk
design and proektirovanie i yazyk
high-level yazyk vysokogo urovnya
low-level yazyk nizkogo urovnya
layout bit-field raspolozhenie bitovyh polej
class objects raspolozhenie ob容ktov klassa
left shift operator operaciya sdviga vlevo
less than operator operaciya men'she chem
than or equal to operator operaciya men'she ili ravno
levels of abstraction urovni abstrakcii
lexical conventions leksicheskie soglasheniya
library biblioteka
design proektirovanie biblioteki
headers biblioteka zagolovochnyh fajlov
initialization inicializaciya biblioteki
lifetime of object vremya zhizni ob容kta
linkage svyazyvanie
consistency soglasovannoe svyazyvanie
error oshibka svyazyvaniya
external vneshnee svyazyvanie
internal vnutrennee svyazyvanie
linker-specification specifikaciya-svyazi
linker redaktor svyazej
Lisp Lisp
list of operator functions spisok operatornyh funkcij
literal literal
constants literal'nye konstanty
loader zagruzchik
local class declaration opisanie lokal'nogo klassa
class member function funkciya-chlen lokal'nogo klassa
class, scope of oblast' vidimosti lokal'nogo klassa
scope lokal'naya oblast' vidimosti
locking blokirovanie (zamok)
logical AND operator operaciya logicheskoe I
OR operator operaciya logicheskoe ILI
negation operator operaciya logicheskogo otricaniya
operators, bitwise porazryadnye logicheskie operacii
long long
constant konstanta long
double long double
double constant konstanta long double
double type tip long double
type tip long
loop statement operator cikla
lvalue adres
assignment and adres i prisvaivanie
cast privedenie adresa
conversion preobrazovanie adresa
modifiable izmenyaemyj adres
M
macro makrokomanda
definition, preprocessing makroopredelenie
expansion, preprocessing makropodstanovka
function-like funkcional'naya makrokomanda
name, scope of oblast' vidimosti makroopredeleniya
names, predefined predopredelennye makroimena
preprocessing makroobrabotka
syntax summary sintaksis makroopredelenij (svodka)
maintenance, software soprovozhdenie programm
management upravlenie
free store upravlenie svobodnoj pamyat'yu
memory upravlenie pamyat'yu
manipulator manipulyator
member chlen
member-declaration opisanie-chlena
member-declarator opisatel'-chlena
member-list spisok-chlenov
modifiable lvalue izmenyaemyj adres
modular programming modul'noe programmirovanie
modularity modul'nost'
multicharacter constant mnogosimvol'naya konstanta
multidimensional array mnogomernyj massiv
multiple inheritance mnozhestvennoe nasledovanie
multiplication operator operaciya umnozheniya
multiplicative-expression mul'tiplikativnoe-vyrazhenie
N
name imya
global global'noe imya
hiding upryatyvanie imeni
length of dlina imeni
linkage of local svyazyvanie lokal'nogo imeni
overloaded function imya peregruzhennoj funkcii
overloaded member imya peregruzhennogo chlena
qualified utochnennoe imya
scope of oblast' vidimosti imeni
nested class declaration opisanie vlozhennogo klassa
class, scope of oblast' vidimosti vlozhennogo klassa
new operator operaciya new
newline \n konec stroki \n
node class uzlovoj klass
null character simvol null '\0'
pointer pustoj ukazatel' (null)
O
object ob容kt
object-oriented programming ob容ktno-orientirovannoe
programmirovanie
octal constant vos'merichnaya konstanta
number vos'merichnoe chislo
operand const operand const
reference operand ssylka
volatile operand volatile
operator , operaciya ,
! operaciya !
# operaciya #
## operaciya ##
%= operaciya %=
&& operaciya &&
&= operaciya &=
*= operaciya *=
*=, user-defined pol'zovatel'skaya operaciya *=
+, user-defined pol'zovatel'skaya operaciya +
++ operaciya ++
++, user-defined pol'zovatel'skaya operaciya ++
+= operaciya +=
-, user-defined pol'zovatel'skaya operaciya -
-- operaciya --
--, user-defined pol'zovatel'skaya operaciya --
-= operaciya -=
->, user-defined pol'zovatel'skaya operaciya ->
/= operaciya /=
:: operaciya ::
<<, output operaciya vyvoda <<
<<= operaciya <<=
=, user-defined pol'zovatel'skaya operaciya =
>>, input operaciya vvoda >>
>>= operaciya >>=
^= operaciya ^=
address-of operaciya vzyatiya adresa
assignment operaciya prisvaivaniya
associativity associativnost' operacij
binding strength poryadok vypolneniya operacij
built-in vstroennye operacii
function call operaciya vyzova funkcii
precedence prioritet operacij
sizeof operaciya sizeof
subscripting operaciya indeksacii
summary svodka operacij
user-defined pol'zovatel'skaya operaciya
operator function operatornaya funkciya
function, list of spisok operatornyh funkcij
order of argument evaluation poryadok vychisleniya parametrov
of evaluation poryadok vychislenij
output formatted formatirovannyj vyvod
input and vvod i vyvod
of built-in type vyvod vstroennyh tipov
of user-defined type vyvod pol'zovatel'skih tipov
operator << operaciya vyvoda <<
overflow perepolnenie
overloaded assignment operator peregruzka operacii prisvaivaniya
binary operator peregruzka binarnoj operacii
decrement operator peregruzka dekrementa
function call operator peregruzka operacii vyzova
function name peregruzka imeni funkcii
increment operator peregruzka inkrementa
member access operator peregruzka operacii vybora chlena
member name peregruzka imeni chlena
operator peregruzka operacii
subscripting operator peregruzka indeksacii
unary operator peregruzka unarnoj operacii
overloading peregruzka
and access peregruzka i dostup
and scope peregruzka i oblast' vidimosti
resolution razreshenie peregruzki
resolution rules pravila razresheniya peregruzki
overriding virtual function pereopredelenie virtual'noj
funkcii
P
paradigm, programming paradigma programmirovaniya
placement ukazanie razmeshcheniya
pointer ukazatel'
arithmetic arifmeticheskie operacii ukazatelej
assignment to prisvaivanie ukazatelyu
comparison sravnenie ukazatelej
const ukazatel' const
conversion preobrazovanie ukazatelej
declaration opisanie ukazatelya
null pustoj ukazatel' null
size of razmer ukazatelya
substraction vychitanie ukazatelej
type tip ukazatelya
postfix ++ and -- postfiksnye ++ i --
expression postfiksnoe vyrazhenie
precedence of operator prioritet operacij
predefined address-of operator predopredelennaya operaciya
vzyatiya adresa
assignment operator predopredelennoe prisvaivanie
macronames predopredelennye makroimena
prefix ++ and -- prefiksnye ++ i --
preprocessing makroobrabotka
directive makrokomanda
directive, error makrokomanda error
directive, null makrokomanda null
directive, pragma makrokomanda pragma
macro definition makroopredelenie
macro expansion makropodstanovka (podstanovka)
syntax summary svodka makrokomand
primary expression pervichnoe vyrazhenie
private private
base class chastnyj bazovyj klass
class member chastnyj chlen klassa
procedural programming procedurnoe programmirovanie
program programma
environment okruzhenie programmy
partitioning razbienie programmy
start zapusk programmy
termination zavershenie programmy
protected protected
member zashchishchennyj chlen
member access dostup k zashchishchennomu chlenu
prototypes prototipy
public public
class member obshchij chlen klassa
pure specifier specifikaciya pure
virtual function chisto virtual'naya funkciya
pure-specifier specifikaciya-pure
Q
qualified name utochnennoe imya
qualified-class-name utochnennoe-imya-klassa
qualified-name utochnennoe-imya
qualified-type-name utochnennoe-imya-tipa
queue empty pustaya ochered'
quote, single odinochnaya kavychka
double dvojnaya kavychka
R
range checking kontrol' diapazona
recursion rekursiya
recursive decent parser analizator rekursivnogo spuska
function call rekursivnyj vyzov funkcii
reference ssylka
assignment prisvaivanie ssylki
assignment to prisvaivanie ssylke
call by vyzov po ssylke
cast privedenie ssylki
conversion preobrazovanie ssylki
const ssylka const
declaration opisanie ssylki
initialization inicializacii ssylki
operand operand ssylka
overloading and peregruzka i ssylka
volatile ssylka volatile
register declaration opisanie register
initialization inicializaciya registra
relational operator operaciya otnosheniya
relational-expression vyrazhenie-otnosheniya
reserved identifier zarezervirovannyj identifikator
resolution ambiguity razreshenie neodnoznachnosti
scoping ambiguity razreshenie neodnoznachnosti
oblasti vidimosti
template function overloading razreshenie peregruzki shablonnoj
funkcii
resource acquisition zapros resursa
exhaustion ischerpanie resursa
release osvobozhdenie resursa
re-throw povtornyj zapusk (osoboj situacii)
return return
return statement operator return
return type tip vozvrashchaemogo znacheniya
run-time error dinamicheskaya oshibka
initialization dinamicheskaya inicializaciya
type information dinamicheskaya informaciya o tipe
S
scope oblast' vidimosti
class oblast' vidimosti klassa
file fajlovaya oblast' vidimosti
function oblast' vidimosti funkcii
global global'naya oblast' vidimosti
local lokal'naya oblast' vidimosti
of label oblast' vidimosti metki
of local class oblast' vidimosti lokal'nogo klassa
of macro name oblast' vidimosti makroimeni
of name oblast' vidimosti imeni
of nested class oblast' vidimosti vlozhennogo klassa
resolution operator operaciya razresheniya oblasti
vidimosti
rules summary svodka pravil oblasti vidimosti
separate compilation razdel'naya translyaciya
shift-expression vyrazhenie-sdviga
short type tip short
type specifier specifikaciya tipa short
side effects pobochnye effekty
sign extension razmnozhenie znaka
signed char type tip signed char
type znakovyj tip
simple-type-name imya-prostogo-tipa
Simula Simula
size of pointer razmer ukazatelya
of string razmer stroki
of structure razmer struktury
sizeof operator operaciya sizeof
Smalltalk Smalltalk
source file ishodnyj fajl
file, inclusion vklyuchenie ishodnogo fajla
special character special'nyj simvol
specifier auto specifikaciya auto
declaration specifikaciya opisaniya
friend specifikaciya friend
function specifikaciya funkcii
inline specifikaciya inline
static specifikaciya static
storage class specifikaciya klassa pamyati
template specifikaciya shablona tipa
typedef specifikaciya typedef
virtual specifikaciya virtual
stack unwinding raskruchivanie steka
standard component standartnyj komponent
conversion standartnoe preobrazovanie
headers standartnye zagolovochnye fajly
include directory standartnyj katalog vklyuchaemyh
fajlov
libraries standartnye biblioteki
statement operator
break operator break
compound sostavnoj operator
continue operator continue
declaration operator opisaniya
do operator do
empty pustoj operator
expression operator vyrazheniya
for operator for
goto operator goto
if operator if
summary svodka operatorov
switch operator switch (pereklyuchatel')
syntax summary sintaksis operatorov
while operator while
static type checking staticheskij kontrol' tipov
static static
class member staticheskij chlen klassa
linkage of svyazyvanie staticheskih
local object staticheskij lokal'nyj ob容kt
member staticheskij chlen
member declaration opisanie staticheskogo chlena
member definition opredelenie staticheskogo chlena
member function staticheskaya funkciya-chlen
specifier specifikaciya static
storage class staticheskij klass pamyati
stream closing of zakrytie potoka
file and fajl i potok
state sostoyanie potoka
string strokovyj potok
string class strokovyj klass
concatenation konkatenaciya strok
constant konstanta stroka
type of tip stroki
wide-character shirokosimvol'naya stroka
struct struct
type specifier specifikaciya tipa struct
structure struktura
initialization of inicializaciya struktury
subclass vlozhennyj klass
subscripting user-defined pol'zovatel'skaya operaciya indeksacii
summary class declaration syntax sintaksis opisanij klassa
compatibility with ANSI C sovmestimost' s ANSI C
compatibility with C sovmestimost' s S
declaration syntax sintaksis opisanij
declarator syntax sintaksis opisatelej
exception handling syntax sintaksis osobyh situacij
expression syntax sintaksis vyrazhenij
macro syntax sintaksis makrokomand
scope rules pravila oblastej vidimosti
statement syntax sintaksis operatorov
template syntax sintaksis shablonov tipa
support for data abstraction podderzhka abstrakcii dannyh
for object-oriented programming podderzhka ob容ktno-orientirovannogo
programmirovaniya
T
template shablon tipa
class shablonnyj klass
class declaration opisanie shablonnogo klassa
class definition opredelenie shablonnogo klassa
declaration opisanie shablona tipa
function shablonnaya funkciya
function declaration opisanie shablonnoj funkcii
function definition opredelenie shablonnoj funkcii
linkage of svyazyvanie shablona tipa
member function shablonnaya funkciya-chlen
specifier specifikaciya template
syntax summary sintaksis shablona tipa
template-arg param-shablona-tipa
template-arg-list spisok-param-shablona-tipa
template-argument parametr-shablona-tipa
template-argument-list spisok-parametrov-shablona-tipa
template-class-name imya-shablonnogo-klassa
template-declaration opisanie-shablona-tipa
temporary vremennyj ob容kt
this this
throw throw
throw-expression vyrazhenie-zapuska
throwing, exception zapusk osoboj situacii
throw-point tochka zapuska
token leksema
tools design proektirovanie servisnyh programm
translation phases stadii translyacii
unit edinica translyacii
trigraph trigraf
try try
try-block proveryaemyj-blok
type tip
user-defined pol'zovatel'skij tip
type-specifier specifikaciya-tipa
U
unary expression unarnoe vyrazhenie
minus operator operaciya unarnyj minus
operator unarnaya operaciya
operator, user-defined pol'zovatel'skaya unarnaya operaciya
plus, operator operaciya unarnyj plyus
unary-expression unarnoe-vyrazhenie
unary-operator unarnaya-operaciya
uncaught exception neperehvachennaya osobaya situaciya
undeclared argument neopisannyj parametr
underscore character simvol podcherkivaniya _
unexpected exceptions neozhidannye osobye situacii
union ob容dinenie
anonymous bezymyannoe ob容dinenie
constructor konstruktor ob容dineniya
destructor destruktor ob容dineniya
discriminating kontroliruemoe ob容dinenie
initialization inicializaciya ob容dineniya
member function funkciya-chlen ob容dineniya
type specifier specifikaciya tipa union
UNIX UNIX
unsigned arithmetic bezznakovaya arifmetika
char type tip unsigned char
constant bezznakovaya konstanta
type bezznakovyj tip
type specifier specifikaciya tipa unsigned
V
vertical tab \v vertikal'naya tabulyaciya \v
virtual virtual
base class virtual'nyj bazovyj klass
destructor virtual'nyj destruktor
function virtual'naya funkciya
function access dostup k virtual'noj funkcii
function call vyzov virtual'noj funkcii
function, type of tip virtual'noj funkcii
specifier specifikaciya virtual
user-defined conversion virtual'noe pol'zovatel'skoe
preobrazovanie
void void
argument pustoj parametr
pointer to ukazatel' tipa void*
type tip void
type specifier specifikaciya tipa void
volatile volatile
member function funkciya-chlen volatile
operand operand volatile
reference ssylka volatile
type tip volatile
type specifier specifikaciya tipa volatile
W
waterfall model model' kaskad
white space obobshchennyj probel
wide-character string shirokosimvol'naya stroka
#include <stream.hxx>
main()
{
cout << "Hello, world\n";
}
#include <stream.hxx>
main ()
{
int inch = 0;
cout << "inches=";
cin >> inch;
cout << inch;
cout << "in = ";
cout << inch*2.54;
cout << " cm\n";
}
#include <stream.hxx>
main()
{
const float fac = 2.54;
float x, in, cm;
char ch = 0;
for ( int i= 0; i< 8; i++) {
cerr << "enter length: ";
cin >> x >> ch;
if (ch == 'i' ) { // inch
in = x;
cm = x*fac;
}
else if (ch == 'c') { // cm
in = x/fac;
cm = x;
}
else
in = cm = 0;
cerr << in << "in = " << cm << " cm\n";
}
}
#include <stream.hxx>
extern float pow(float, int);
main()
{
for (int i=0; i<10; i++) cout << pow(2,i) << "\n";
}
extern void error(char *);
float pow(float x, int n)
{
if (n < 0) {
error ("sorry, negative exponent to pow()");
return 0;
}
switch (n) {
case 0: return 1;
case 1: return x;
default: return x*pow(x,n-1);
}
}
void error(char *s)
{
cout << s;
}
#include <stream.hxx>
// 1.11
class vector {
int *v;
int sz;
public:
vector(int); // constructor
~vector(); // destructor
int size() { return sz; }
void set_size(int);
int& operator[](int);
int& elem(int i) { return v[i]; }
};
// 1.13
class vec : public vector {
int low, high;
public:
vec(int, int);
int& elem(int);
int& operator[](int);
};
main()
{
vector a(10);
for (int i=0; i<a.size(); i++) {
a[i] = i;
cout << a[i] << " ";
}
cout << "\n";
vec b(10,19);
for (i=0; i<b.size(); i++) b[i+10] = a[i];
for (i=0; i<b.size(); i++) cout << b[i+10] << " ";
cout << "\n";
}
extern void exit(int);
// 1.13
void error(char* p)
{
cerr << p << "\n";
exit (1);
}
// 1.11
vector::vector(int s)
{
if (s<=0) error("bad vector size");
sz = s;
v = new int[s];
}
int& vector::operator[](int i)
{
if (i<0 || sz<=i) error("vector index out of range");
return v[i];
}
vector::~vector()
{
delete v;
}
// 1.13
int& vec::elem(int i)
{
return vector::elem(i-low);
}
vec::vec(int lb, int hb) : (hb-lb+1)
{
if (hb-lb<0) hb = lb;
low = lb;
high = hb;
}
void vector::set_size(int) { /* dummy */ }
int& vec::operator[](int i)
{
if (i<low || high<i) error("vec index out of range");
return elem(i);
}
#include<stream.hxx>
extern void exit( int );
extern void error( char* );
// 1.11
class vector {
int *v;
int sz;
public:
vector(int); // constructor
~vector(); // destructor
int size() { return sz; }
void set_size(int);
int& operator[](int);
int& elem(int i) { return v[i]; }
};
vector::vector(int s)
{
if (s<=0) error("bad vector size");
sz = s;
v = new int[s];
}
int& vector::operator[](int i)
{
if (i<0 || sz<=i) error("vector index out of range");
return v[i];
}
vector::~vector()
{
delete v;
}
// 1.14
class Vec : public vector {
public:
Vec(int s) : (s) {}
Vec(Vec&);
~Vec() {}
void operator=(Vec&);
void operator*=(Vec&);
void operator*=(int);
};
Vec::Vec(Vec& a) : (a.size())
{
int sz = a.size();
for (int i = 0; i<sz; i++) elem(i) =a.elem(i);
}
void Vec::operator=(Vec& a)
{
int s = size();
if (s!=a.size()) error("bad vector size for =");
for (int i =0; i<s; i++) elem(i)=a.elem(i);
}
Vec operator+(Vec& a, Vec& b)
{
int s = a.size();
if (s != b.size()) error("bad vector size for +");
Vec sum(s);
for (int i=0; i<s; i++)
sum.elem(i) = a.elem(i) + b.elem(i);
return sum;
}
void error(char* p)
{
cerr << p << "\n";
exit (1);
}
void vector::set_size(int) { }
main()
{
Vec a(10);
Vec b(10);
for (int i=0; i<a.size(); i++) a[i] = i;
b = a;
Vec c = a+b;
for (i=0; i<c.size(); i++) cout << c[i] << "\n";
}
#include <vector.hxx>
declare(vector,int);
implement(vector,int);
main()
{
vector(int) vv(10);
vv[2] = 3;
vv[10] = 4; // range error
}
#include <stream.hxx>
int a = 1;
void f()
{
int b = 1;
static int c = 1;
cout << " a = " << a++
<< " b = " << b++
<< " c = " << c++ << "\n";
}
main ()
{
while (a < 4) f();
}
#include <stream.hxx>
main()
{
int* p = new int;
cout << "sizeof(int) = " << sizeof(int) "\n";
}
#include <stream.hxx>
extern int strlen(char*);
char alpha[] = "abcdefghijklmnopqrstuvwxyz";
main ()
{
int sz = strlen(alpha);
for (int i=0; i<sz; i++) {
char ch = alpha[i];
cout << "'" << chr(ch) << "'"
<< " = " << ch
<< " = 0" << oct(ch)
<< " = 0x" << hex(ch) << "\n";
}
}
#include <stream.hxx>
char v[2][5] = {
'a', 'b', 'c', 'd', 'e',
'0', '1', '2', '3', '4'
};
main() {
for ( int i = 0; i<2; i++) {
for (int j = 0; j <5; j++)
cout << "v[" << i << "][" << j
<< "]=" << chr(v[i][j]) << " ";
cout << "\n";
}
}
#include <stream.hxx>
main()
{
char cv[10];
int iv[10];
char* pc = cv;
int* pi = iv;
cout << "char* " << long(pc+1)-long(pc) << "\n";
cout << "int* " << long(pi+1)-long(pi) << "\n";
}
#include <stream.hxx>
struct pair {
char* name;
int val;
};
extern int strlen(char*);
extern int strcpy(char*, char*);
extern int strcmp(char*, char*);
const large = 1024;
static pair vec[large];
pair* find(char* p)
{
for (int i=0; vec[i].name; i++)
if (strcmp(p,vec[i].name)==0) return &vec[i];
if (i== large) return &vec[large-1];
return &vec[i];
}
int& value(char* p)
{
pair* res = find(p);
if (res->name == 0) {
res->name = new char[strlen(p)+1];
strcpy(res->name,p);
res->val = 0;
}
return res->val;
}
const MAX = 256;
main ()
{
char buf [MAX];
while ( cin>>buf) value(buf)++;
for (int i=0; vec[i].name; i++)
cout << vec[i].name << ":" << vec[i].val << "\n";
}
#include <xstream.hxx>
#include <ctype.h>
enum token_value {
NAME, NUMBER, END,
PLUS = '+', MINUS = '-', MUL='*', DIV='/',
PRINT=';', ASSIGN='=', LP='(', RP=')'
};
token_value curr_tok;
struct name {
char* string;
name* next;
double value;
};
const TBLSZ = 23;
name* table[TBLSZ];
int no_of_errors;
double error(char* s) {
cerr << "error: " << s << "\n";
no_of_errors++;
return 1;
}
extern int strlen(const char*);
extern int strcmp(const char*, const char*);
extern char* strcpy(char*, const char*);
name* look(char* p, int ins = 0)
{
int ii= 0;
char *pp = p;
while (*pp) ii = ii<<1 ^ *pp++;
if (ii < 0) ii = -ii;
ii %= TBLSZ;
for (name* n=table [ii]; n; n=n->next)
if (strcmp(p,n->string) == 0) return n;
if (ins == 0) error("name not found");
name* nn = new name;
nn->string = new char[strlen(p) + 1];
strcpy(nn->string,p);
nn->value = 1;
nn->next = table[ii];
table[ii] = nn;
return nn;
}
inline name* insert(char* s) { return look (s,1); }
token_value get_token();
double term();
double expr()
{
double left = term();
for (;;)
switch (curr_tok) {
case PLUS:
get_token();
left += term();
break;
case MINUS:
get_token();
left -= term();
break;
default :
return left;
}
}
double prim();
double term()
{
double left = prim();
for (;;)
switch (curr_tok) {
case MUL:
get_token();
left *= prim();
break;
case DIV:
get_token();
double d = prim();
if (d == 0) return error("divide by o");
left /= d;
break;
default:
return left;
}
}
int number_value;
char name_string[80];
double prim()
{
switch (curr_tok) {
case NUMBER:
get_token();
return number_value;
case NAME:
if (get_token() == ASSIGN) {
name* n = insert(name_string);
get_token();
n->value = expr();
return n->value;
}
return look(name_string)->value;
case MINUS:
get_token();
return -prim();
case LP:
get_token();
double e = expr();
if (curr_tok != RP) return error(") expected");
get_token();
return e;
case END:
return 1;
default:
return error ("primary expected");
}
}
token_value get_token()
{
char ch = 0;
do {
if(!cin.get(ch)) return curr_tok = END;
} while (ch!='\n' && isspace(ch));
switch (ch) {
case ';':
case '\n':
cin >> WS;
return curr_tok=PRINT;
case '*':
case '/':
case '+':
case '-':
case '(':
case ')':
case '=':
return curr_tok=ch;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '.':
cin.putback(ch);
cin >> number_value;
return curr_tok=NUMBER;
default:
if (isalpha(ch)) {
char* p = name_string;
*p++ = ch;
while (cin.get(ch) && isalnum(ch)) *p++ = ch;
cin.putback(ch);
*p = 0;
return curr_tok=NAME;
}
error ("bad token");
return curr_tok=PRINT;
}
}
int main(int argc, char* argv[])
{
switch (argc) {
case 1:
break;
case 2:
cin = *new istream(strlen(argv[1]),argv[1]);
break;
default:
error("too many arguments");
return 1;
}
// insert predefined names:
insert("pi")->value = 3.1415926535897932385;
insert("e")->value = 2.7182818284590452354;
while (1) {
get_token();
if( curr_tok == END) break;
if (curr_tok == PRINT) continue;
cout << expr() << "\n";
}
return no_of_errors;
}
extern void strcpy(char *,char *);
extern void exit(int);
extern int strlen(char *);
char *save_string(char* p)
{
char* s = new char[strlen(p)+1];
strcpy(s,p);
return s;
}
int main (int argc, char* argv[])
{
if (argc < 2) exit(1);
int size = strlen(argv[1])+1;
char* p = save_string (argv[1]);
delete[size] p;
}
#include <stream.hxx>
extern void exit( int );
void out_of_store()
{
cout << "operator new failed: out of store\n";
exit(1);
}
typedef void (*PF)();
extern PF set_new_handler(PF);
main()
{
set_new_handler(&out_of_store);
char *p = new char[100000000];
cout << "done, p = " << long(p) << "\n";
}
// This version of the program does not assume sizeof(int)==sizeof(char*) !
#include <stream.hxx>
#include <stdarg.hxx>
extern void exit(int);
void error (int ...);
main(int argc, char* argv[])
{
switch (argc) {
case 1:
error(0,argv[0],(char*)0);
break;
case 2:
error(0,argv[0],argv[1],(char*)0);
break;
default :
error(1,"with",dec(argc-1),"arguments",(char*)0);
}
}
void error(int n ...)
{
va_list ap;
va_start(ap,n);
for (;;) {
char *p = va_arg(ap,char*);
if (p == 0) break;
cerr << p << " ";
}
va_end(ap);
cerr << "\n";
if (n) exit(n);
}
#include <stream.hxx>
struct user {
char *name;
char* id;
int dept;
};
typedef user* Puser;
user heads[] = {
"Mcilroy M.D", "doug", 11271,
"Aho A.v.", "ava", 11272,
"Weinberger P.J.", "pjw", 11273,
"Schryer N.L.", "nls", 11274,
"Schryer N.L.", "nls", 11275,
"Kernighan B.W.", "bwk", 11276
};
typedef int (*CFT)(char*,char*);
void sort(char* base, unsigned n, int sz, CFT cmp)
{
for (int i=0; i<n-1; i++)
for (int j=n-1; i<j; j--) {
char* pj = base+j*sz;
char *pj1 = pj-sz;
if ((*cmp)(pj,pj1) < 0)
// swap b[j] and b[j-1]
for (int k=0; k<sz; k++) {
char temp = pj[k];
pj[k] = pj1[k];
pj1[k] = temp;
}
}
}
void print_id(Puser v, int n)
{
for (int i=0; i<n; i++)
cout << v[i].name << "\t"
<< v[i].id << "\t"
<< v[i].dept << "\n";
}
extern int strcmp(char*, char*);
int cmp1(char* p, char* q)
{
return strcmp(Puser(p)->name, Puser(q)->name);
}
int cmp2(char* p, char* q)
{
return Puser(p)->dept - Puser(q)->dept;
}
main ()
{
sort((char*)heads,6,sizeof(user),cmp1);
print_id(heads,6);
cout << "\n";
sort ((char*)heads,6,sizeof(user),cmp2);
print_id(heads,6); // in department number order
}
#include <stream.hxx>
class intset {
int cursize, maxsize;
int *x;
public:
intset(int m, int n);
~intset();
int member(int t);
void insert(int t);
void iterate(int& i) { i = 0; }
int ok(int& i) { return i<cursize; }
int next(int& i) { return x[i++]; }
};
extern void exit (int);
void error(char *s)
{
cout << "set: " << s << "\n";
exit(1);
}
extern int atoi(char *);
extern int rand();
int randint (int u) // in the range 1..u
{
int r = rand();
if (r < 0) r = -r;
return 1 + r%u ;
}
intset::intset(int m, int n)
{
if (m<1 || n<m) error("illegal intset size");
cursize = 0;
maxsize = m;
x = new int[maxsize];
}
intset::~intset()
{
delete x;
}
void intset::insert(int t)
{
if (++cursize > maxsize) error("too many elements");
int i = cursize-1;
x[i] = t;
while (i>0 && x[i-1]>x[i]) {
int t = x[i];
x[i] = x[i-1];
x[i-1] = t;
i--;
}
}
int intset::member(int t)
{
int l = 0;
int u = cursize-1;
int m =0;
while (l <= u) {
m = (l+u)/2;
if (t < x[m])
u = m-1;
else if (t > x[m])
l = m+1;
else
return 1; // found
}
return 0; // not found
}
void print_in_order(intset* set)
{
int var;
set->iterate(var);
while (set->ok(var)) cout << set->next(var) << "\n";
}
main (int argc, char *argv[])
{
if (argc != 3) error("two arguments expected");
int count = 0;
int m = atoi(argv[1]);
int n = atoi (argv[2]);
intset s(m,n);
int t = 0;
while (count <m) {
t = randint(n);
if (s.member(t)==0) {
s.insert(t);
count++;
}
}
print_in_order(&s);
}
#include <stream.hxx>
struct cl
{
char* val;
void print(int x) { cout << val << x << "\n"; }
cl(char *v) { val = v; }
};
typedef void (cl::*PROC)(int);
main()
{
cl z1("z1 ");
cl z2("z2 ");
PROC pf1 = &cl::print;
PROC pf2 = &cl::print;
z1.print(1);
(z1.*pf1)(2);
z2.print(3);
((&z2)->*pf2)(4);
}
main() {
char *p = new char[100];
char *q = new char[100];
delete p;
delete p;
}
#include "stream.hxx"
int error (char * p)
{
cout << p << "\n";
return 1;
}
class tiny {
char v;
tiny assign(int i)
{ v = (i&~63) ? (error("range error"),0) : i; return *this; }
public:
tiny (int i) { assign(i); }
tiny (tiny& t) { v = t.v; }
tiny operator=(tiny& t1) { v = t1.v; return *this; }
tiny operator=(int i ) { return assign(i); }
int operator int() { return v; }
};
void main()
{
tiny c1 = 2;
tiny c2 = 62;
tiny c3 = (c2 - c1);
tiny c4 = c3;
int i = (c1 + c2);
c1 = (c2 + (2 * c1));
c2 = c1 - i;
c3 = c2;
}
#include <stream.hxx>
extern int strcpy(char* , char*);
extern int strlen(char *);
struct string {
char *p;
int size;
inline string(int sz) { p = new char[size=sz]; }
string(char *);
inline ~string() { delete p; }
void operator=(string&);
string(string& );
};
string::string(char* s)
{
p = new char [size = strlen(s) + 1];
strcpy (p,s);
}
void string::operator=(string& a)
{
if (this == &a) return;
delete p;
p=new char[size=a.size];
strcpy(p,a.p);
}
string::string(string& a)
{
p=new char[size=a.size];
strcpy(p,a.p);
}
string g(string arg)
{
return arg;
}
main()
{
string s = "asdf";
s = g(s);
cout << s.p << "\n";
}
#include <stream.hxx>
#include <string.h>
struct pair {
char * name;
int val;
};
class assoc {
pair * vec;
int max;
int free;
public:
assoc(int);
int& operator[](char* );
void print_all();
};
assoc::assoc(int s)
{
max = (s<16) ? s: 16;
free = 0;
vec = new pair[max];
}
int& assoc::operator[](char * p)
/*
maintain a set of "pair"s
search for p,
return a reference to the integer part of its "pair"
make a new "pair" if "p" has not been seen
*/
{
register pair* pp;
for (pp=&vec[free-1]; vec<=pp; pp-- )
if (strcmp(p, pp->name)==0) return pp->val;
if (free==max) { // overflow: grow the vector
pair* nvec = new pair[max*2];
for (int i=0; i<max; i++) nvec[i] = vec[i];
delete vec;
vec = nvec;
max = 2*max;
}
pp = &vec[free++];
pp->name = new char[strlen(p)+1];
strcpy(pp->name,p);
pp->val = 0;
return pp->val;
}
void assoc::print_all()
{
for (int i=0; i<free; i++)
cout << vec[i].name << ": " << vec[i].val << "\n";
}
main()
{
const MAX = 256;
char buf[MAX];
assoc vec(512);
while ( cin>>buf) vec[buf]++;
vec.print_all();
}
#include <stream.hxx>
#include <string.h>
struct pair {
char* name;
int val;
};
class assoc {
friend class assoc_iterator;
pair* vec;
int max;
int free;
public:
assoc(int);
int& operator[](char*);
};
class assoc_iterator {
assoc* cs;
int i;
public:
assoc_iterator(assoc& s) { cs = &s; i = 0; }
pair* operator()()
{ return (i<cs->free)? &cs->vec[i++] : 0; }
};
assoc::assoc(int s)
{
max = (s<16) ? s : 16;
free = 0;
vec = new pair[max];
}
int& assoc::operator[](char* p)
{
register pair* pp;
for (pp=&vec[free-1]; vec<=pp; pp-- )
if (strcmp(p,pp->name)==0) return pp->val;
if (free ==max) {
pair* nvec = new pair[max*2];
for (int i=0; i<max; i++) nvec[i] = vec[i];
delete vec;
vec = nvec;
max = 2*max;
}
pp = &vec[free++];
pp->name = new char[strlen(p)+1];
strcpy(pp->name,p);
pp->val = 0;
return pp->val;
}
main()
{
const MAX = 256;
char buf[MAX];
assoc vec(512);
while ( cin>>buf) vec[buf]++;
assoc_iterator next(vec);
pair* p;
while (p = next() )
cout << p->name << ": " << p->val << "\n";
}
#include <stream.hxx>
#include <string.h>
extern void exit(int);
class string {
struct srep {
char* s;
int n;
};
srep *p;
public:
string(char *);
string();
string(string &);
string& operator=(char *);
string& operator=(string &);
~string();
char& operator[](int i);
friend ostream& operator<<(ostream&, string&);
friend istream& operator>> (istream&, string&);
friend int operator==(string &x, char *s)
{ return strcmp(x.p->s, s) == 0; }
friend int operator==(string &x, string &y)
{ return strcmp(x.p->s, y.p->s) == 0; }
friend int operator!=(string &x, char *s)
{ return strcmp(x.p->s, s) != 0; }
friend int operator!=(string &x, string &y)
{ return strcmp (x.p->s, y.p->s) != 0; }
};
string::string()
{
p = new srep;
p->s = 0;
p->n = 1;
}
string::string(char* s)
{
p = new srep;
p->s = new char[ strlen(s) +1];
strcpy(p->s, s);
p->n = 1;
}
string::string(string& x)
{
x.p->n++;
p = x.p;
}
string::~string()
{
if (--p->n == 0){
delete p->s;
delete p;
}
}
string& string::operator=(char* s)
{
if (p->n > 1) {
p->n--;
p = new srep;
}
else if (p->n == 1)
delete p->s;
p->s = new char[ strlen(s)+1 ];
strcpy(p->s, s);
p->n = 1;
return *this;
}
string& string::operator=(string& x)
{
x.p->n++;
if (--p->n == 0) {
delete p->s;
delete p;
}
p = x.p;
return *this;
}
ostream& operator<<(ostream& s, string& x)
{
return s << x.p->s << " [" << x.p->n << "]\n";
}
istream& operator>>(istream& s, string& x)
{
char buf[256];
s>>buf;
x = buf;
cout << "echo: " << x << "\n";
return s;
}
void error(char* p)
{
cout << p << "\n";
exit(1);
}
char& string::operator[](int i)
{
if (i<0 || strlen(p->s)<i) error("index out of range");
return p->s[i];
}
main()
{
string x[100];
int n;
cout << "here we go\n";
for (n = 0; cin>>x[n]; n++) {
string y;
if (n==100) error("too many strings");
cout << (y = x[n]);
if (y=="done") break;
}
cout << "here we go back again\n";
for (int i=n-1; 0<=i; i--) cout << x[i];
}
#include <stream.hxx>
struct employee {
friend class manager;
employee* next;
char* name;
short department;
virtual void print();
};
struct manager : employee {
employee* group;
short level;
void print();
};
void employee::print()
{
cout << name << "\t" << department << "\n";
}
void manager::print()
{
employee::print();
cout << "\tlevel " << level << "\n";
}
void f(employee* ll)
{
for ( ; ll; ll=ll->next) ll->print();
}
main ()
{
employee e;
e.name = "J. Brown";
e.department = 1234;
e.next = 0;
manager m;
m.name = "J. Smith";
m.department = 1234;
m.level = 2;
m.next = &e;
f(&m);
}
#include <stream.hxx>
struct base { base(); };
struct derived : base { derived(); };
base:: base()
{
cout << "\tbase 1: this=" << long(this) << "\n";
if (this == 0) this = (base*)27;
cout << "\tbase 2: this=" << long(this) << "\n";
}
derived::derived()
{
cout << "\tderived 1: this=" << long(this) << "\n";
if (this == 0) this = (derived*)43;
cout << "\tderived 2: this=" << long(this) << "\n";
}
main()
{
cout << "base b;\n";
base b;
cout << "new base;\n";
new base;
cout << "derived d;\n";
derived d;
cout << "new derived;\n";
new derived;
cout << "new derived;\n";
new derived;
cout << "at the end\n";
}
#include <xstream.hxx>
extern void exit(int);
void error(char* s, char* s2)
{
cerr << s << " " << s2 << "\n";
exit(1);
}
main(int argc, char* argv[])
{
if (argc != 3) error ("wrong number of arguments","");
filebuf f1;
if (f1.open(argv[1],input) == 0)
error("cannot open input file",argv[1]);
istream from(&f1);
filebuf f2;
if (f2.open(argv[2],output) == 0)
error("cannot open input file",argv[2]);
ostream to(&f2);
char ch;
while (from.get(ch)) to.put(ch);
if (!from.eof() || to.bad())
error("something strange happened","");
}
Last-modified: Wed, 08 May 2002 14:07:44 GMT