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. R.6 Operatory 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. R.6.4.1 Operator if 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. R.6.5 Operatory cikla |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. R.6.5.1 Operator while 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). R.6.5.2 Operator do 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). R.6.5.3 Operator for 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. R.6.6 Operatory perehoda 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). R.6.6.1 Operator break 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. R.6.6.3 Operator return 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. R.6.6.4 Operator goto Operator goto bezuslovno peredaet upravlenie na operator, pomechennyj identifikatorom. Identifikator dolzhen byt' metkoj ($$R.6.1), nahodyashchejsya v tekushchej funkcii. R.6.7 Operator opisaniya 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 } R.7 Opisaniya 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. R.7.1 Specifikacii 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 // ... } R.7.3 Opisaniya asm 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). R.8 Opisateli 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). R.8.1 Imena tipov 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 } R.8.2 Smysl opisatelej 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 n