Все работает отлично.
10
Ñ++. Åñëè âû ïðèíàäëåæèòå ê èõ ÷èñëó, ÿ ñîæàëåþ, ÷òî çàäåë âàøè ÷óâñòâà. Ïóñòü íå òàê ñèëüíî,
÷òîáû ëèøèòüñÿ ñíà, íî âñå æå ñîæàëåþ.
ß íå ïðåòåíäóþ íà àâòîðñòâî èçëîæåííûõ â êíèãå èäåé. Åñëè âû óâèäèòå â íåé ÷òî-òî, ïðèäóìàííîå
âàìè èëè êåì-òî äðóãèì, — ñìåëî çàÿâëÿéòå, ÷òî ýòî âàøèõ ðóê äåëî, ñïîðèòü ÿ íå ñòàíó. Ìàñòåðñòâî
íåòðèâèàëüíîãî èñïîëüçîâàíèÿ Ñ++ ðàñòåò îò ñâîáîäíîãî îáìåíà èäåÿìè, à íå îò ôîðìàëüíîãî
èçó÷åíèÿ, òàê ÷òî â äåéñòâèòåëüíîñòè î÷åíü òðóäíî îäíîçíà÷íî îïðåäåëèòü, êòî, ÷òî è êîãäà ñêàçàë. ß
íàïèñàë ýòó êíèãó, ÷òîáû êàê ìîæíî áîëüøå ëþäåé ñìîãëè áûñòðî è áåçáîëåçíåííî ïîâûñèòü ñâîþ
êâàëèôèêàöèþ, ïîýòîìó âîïðîñàì àâòîðñòâà èäåé óäåëÿëîñü âòîðîñòåïåííîå âíèìàíèå. Åñëè âàì ýòî íå
íðàâèòñÿ, ïðèìèòå ìîè èñêðåííèå èçâèíåíèÿ è íàïèøèòå ñâîþ ñîáñòâåííóþ êíèãó.
Ñ äðóãîé ñòîðîíû, ÿ âçÿë íà ñåáÿ ñìåëîñòü èñïîëüçîâàòü íîâûå èìåíà äëÿ ñòàðûõ êîíöåïöèé,
âûçûâàþùèõ íåäîðàçóìåíèÿ, è íèñêîëüêî îá ýòîì íå æàëåþ. Òàêîâà óæ âåëèêàÿ òðàäèöèÿ ñîîáùåñòâà
Ñ++, êîòîðîå ïåðåèìåíîâàëî ïî÷òè âñå îáúåêòíî-îðèåíòèðîâàííûå êîíöåïöèè: ñóáêëàññ (ïðîèçâîäíûé
êëàññ), ñóïåðêëàññ (áàçîâûé êëàññ), ìåòîä (ôóíêöèÿ êëàññà) è ò.ä. Ñòîðîííèêè ïåðåèìåíîâàíèÿ íå
îáîøëè âíèìàíèåì äàæå òàêèå òðàäèöèîííûå êîíöåïöèè Ñ, êàê ïîðàçðÿäíûé ñäâèã (<< è >>). Âàì íå
íðàâèòñÿ, ÷òî äëÿ ñòàðûõ èäåé èñïîëüçóþòñÿ íîâûå èìåíà, — ïóñòü äàæå â èíòåðåñàõ ÿñíîñòè?
Ïðèÿòåëü, âû îøèáëèñü ñ âûáîðîì ÿçûêà.
ß ñäåëàë âñå âîçìîæíîå, ÷òîáû âñå ôðàãìåíòû êîäà â ýòîé êíèãå ðàáîòàëè êàê ïîëîæåíî, íî áåç
îøèáîê äåëî íàâåðíÿêà íå îáîøëîñü. Äåéñòâóéòå òàê, ñëîâíî âàøà ïðîãðàììó óæå ãîðèò ñèíèì
ïëàìåíåì, — ïðîâåðÿéòå, ïðîâåðÿéòå è åùå ðàç ïðîâåðÿéòå ìîé êîä, ïðåæäå ÷åì èñïîëüçîâàòü åãî â
ñâîèõ ïðîãðàììàõ. Ïîìíèòå: â ýòîé êíèãå ÿ äåìîíñòðèðóþ ðàçëè÷íûå èäèîìû è êîíöåïöèè, à íå
ñîçäàþ áèáëèîòåêó êëàññîâ. Âñå èäèîìû âïîëíå ðàáîòîñïîñîáíû, íî äàëüøå âàì ïðèäåòñÿ äåéñòâîâàòü
ñàìîñòîÿòåëüíî.
Äæåôô Ýëäæåð
ßíâàðü 1998 ã.

Ââåäåíèå
è êðàòêèé îáçîð
 ýòîé ÷àñòè ÿ îòâå÷àþ íà ãëàâíûé âîïðîñ: «Çà÷åì áûëî ïèñàòü åùå îäíó
êíèãó î Ñ++»? Äàëåå â ãîëîâîêðóæèòåëüíîì òåìïå ðàññìàòðèâàþòñÿ
íåêîòîðûå íåòðèâèàëüíûå âîçìîæíîñòè ÿçûêà. Âñå ýòî äåëàåòñÿ
èñêëþ÷èòåëüíî äëÿ ïîäãîòîâêè ê ñëåäóþùèì ãëàâàì, ïîýòîìó ìàòåðèàë
ìîæíî ÷èòàòü èëè ïðîïóñêàòü â çàâèñèìîñòè îò òîãî, íàñêîëüêî óâåðåííî
âû âëàäååòå òåìè èëè èíûìè òîíêîñòÿìè ñèíòàêñèñà Ñ++.
1 ×àñòü


Çà÷åì íóæíà
åùå îäíà êíèãà î
Ñ++?
Ïî ïîñëåäíèì äàííûì, íà ðûíêå ïðîäàåòñÿ ïî êðàéíåé ìåðå 2 768 942 êíèãè î Ñ++, íå ãîâîðÿ óæå î
âñåâîçìîæíûõ êóðñàõ, îáó÷àþùèõ ïðîãðàììàõ, æóðíàëàõ è ñåìèíàðàõ ñ êîêòåéëÿìè. È âñå æå â ýòîì
èçîáèëèè íàáëþäàåòñÿ óäðó÷àþùåå îäíîîáðàçèå. Ïðîñìàòðèâàòü ïîëêó êíèã î Ñ++ â êíèæíîì
ìàãàçèíå íè÷óòü íå èíòåðåñíåå, ÷åì ëèòåðàòóðó ïî áóõãàëòåðèè.  ñóùíîñòè, âñå êíèãè ïåðåñêàçûâàþò
îäíî è òî æå è îòëè÷àþòñÿ ðàçâå ÷òî ïî âåñó è êîëè÷åñòâó öâåòîâ â äèàãðàììàõ è òàáëèöàõ. Ïî ìîèì
ïîäñ÷åòàì, 2 768 940 èç íèõ ïðåäíàçíà÷åíû äëÿ íîâè÷êîâ, îðèåíòèðîâàíû íà êîíêðåòíûé êîìïèëÿòîð
èëè ïðåäñòàâëÿþò ñîáîé ñïðàâî÷íèêè ïî ñèíòàêñèñó Ñ++. Äëÿ òåõ, êòî óæå çíàåò ÿçûê è æåëàåò
ïîäíÿòüñÿ íà ñëåäóþùèé óðîâåíü, ñóùåñòâóþùàÿ ñèòóàöèÿ îáîðà÷èâàåòñÿ ñïëîøíûìè
ðàçî÷àðîâàíèÿìè è ðàñõîäàìè. ×òîáû óçíàòü ÷òî-òî íîâîå, ïðèõîäèòñÿ äåðãàòü ãëàâó îòñþäà è ðàçäåë
îòòóäà. Äëÿ çíàòîêà Ñ++ òàêàÿ òðàòà âðåìåíè íåïîçâîëèòåëüíà.
Ýòà êíèãà — ñîâñåì äðóãîå äåëî. Ïðåæäå âñåãî, îíà ïðåäïîëàãàåò, ÷òî âû óæå âëàäååòå Ñ++. Âåðîÿòíî,
âû ïðîãðàììèðîâàëè íà Ñ++ â òå÷åíèå ãîäà-äâóõ èëè áîëåå. Ñòàâ íàñòîÿùèì àñîì, íà âîïðîñ î
äîëæíîñòè âû ïåðåñòàëè ñêðîìíî îòâå÷àòü «Ïðîãðàììèñò»; òåïåðü âàø òèòóë ñêëàäûâàåòñÿ èç ñëîâ
«Ñòàðøèé», «Ñïåöèàëèñò», «Âåäóùèé», «Ðàçðàáîò÷èê», «Ïðîåêòèðîâùèê» (ðàññòàâüòå â íóæíîì
ïîðÿäêå). Âû óæå çíàåòå, ÷òî «ïåðåãðóçêà îïåðàòîðà» íå èìååò íèêàêîãî îòíîøåíèÿ ê òåëåôîííîé
êîìïàíèè, à «êëàññ-êîëëåêöèÿ» — âîâñå íå ñáîðèùå ôèëàòåëèñòîâ. Íà âàøåé ïîëêå ñòîèò êíèãà
Ñòðàóñòðóïà «Annotated C++ Reference Manual», êîòîðóþ â ïðîôåññèîíàëüíûõ ðàçãîâîðàõ âû ÷àñòî
ñîêðàùåííî èìåíóåòå ARM è äàæå íå ñ÷èòàåòå íóæíûì ðàñøèôðîâûâàòü.
Åñëè âû óçíàëè ñåáÿ, äîáðî ïîæàëîâàòü — ýòà êíèãà äëÿ âàñ. Åå ìîæíî áûëî áû åùå íàçâàòü «Ñ++:
ïóòü ãóðó». Ñ++ â íåé îïèñûâàåòñÿ ñîâñåì íå òàê, êàê â êíèãàõ äëÿ íà÷èíàþùèõ. Íà ýòîì óðîâíå Ñ++
— íå ñòîëüêî ÿçûê, ñêîëüêî öåëàÿ ñóáêóëüòóðà ñî ñâîèìè èäèîìàìè, ïðèåìàìè è ñòàíäàðòíûìè
àðõèòåêòóðíûìè ðåøåíèÿìè, êîòîðûå íå ñëåäóþò î÷åâèäíûì îáðàçîì èç ôîðìàëüíîãî îïèñàíèÿ ÿçûêà.
Îá ýòîì «ÿçûêå âíóòðè ÿçûêà» ðåäêî óïîìèíàåòñÿ ñ êíèãàõ è æóðíàëàõ. Îäíè ïðîãðàììèñòû
ñàìîñòîÿòåëüíî îáíàðóæèâàþò âñå ýòè âîçìîæíîñòè è ñ ãîðäîñòüþ ñ÷èòàþò, ÷òî èçîáðåëè íå÷òî
ïîòðÿñàþùåå, ïîêà íå âûÿñíèòñÿ, ÷òî «íåò íè÷åãî íîâîãî ïîä ñîëíöåì». Äðóãèì âåçåò, è îíè
ñòàíîâÿòñÿ ó÷åíèêàìè ïîäëèííûõ ìàñòåðîâ Ñ++ — ê ñîæàëåíèþ, òàêèå ìàñòåðà âñòðå÷àþòñÿ ñëèøêîì
ðåäêî. Â ýòîé êíèãå ÿ ïîïûòàëñÿ ïðîëîæèòü òðåòèé ïóòü èñòèííîãî ïðîñâåòëåíèÿ — ñàìîñòîÿòåëüíîå
èçó÷åíèå. Êðîìå òîãî, êíèãà ïðåäíàçíà÷åíà äëÿ òåõ, êòî óæå äîñòèã çàâåòíîé öåëè, íî õî÷åò
ïîîáùàòüñÿ, ïîáîëòàòü â äðóæåñêîé êîìïàíèè è ïîøåâåëèòü ìîçãàìè íàä î÷åðåäíîé ãîëîâîëîìêîé.
Äàî Ñ++
Ñ++ — ÿçûê, êîòîðûé èçó÷àåòñÿ ïîñòåïåííî. Ëèøü ïîñëå òîãî, êàê áóäåò ñäåëàí ïîñëåäíèé øàã,
ðàçðîçíåííûå ïðèåìû è ôðàãìåíòû ñèíòàêñèñà íà÷èíàþò ñêëàäûâàòüñÿ â îáùóþ êàðòèíó. Ïî-ìîåìó,
èçó÷åíèå Ñ++ ÷åì-òî íàïîìèíàåò ïîäúåì íà ëèôòå. Äçûíü! Âòîðîé ýòàæ. Ñ++ — ýòî
óñîâåðøåíñòâîâàííûé âàðèàíò Ñ, ñ ñèëüíîé òèïèçàöèåé (êîòîðóþ, âïðî÷åì, ïðè æåëàíèè ìîæíî
îáîéòè) è óäîáíûìè êîììåíòàðèÿìè //. Ëþáîé ïðîãðàììèñò íà Ñ, åñëè îí íå õî÷åò ïîäàâàòüñÿ â
ìåíåäæåðû, äîëæåí äâèãàòüñÿ äàëüøå… à Áüÿðí Ñòðàóñòðóï (Ãîñïîäè, áëàãîñëîâè åãî) ïðèäóìàë äëÿ
ýòîãî îòëè÷íóþ âîçìîæíîñòü.
1

14
Äçûíü! Òðåòèé ýòàæ. Ñ++ — õîðîøèé, õîòÿ è íå ïîòðÿñàþùèé îáúåêòíî-îðèåíòèðîâàííûé ÿçûê
ïðîãðàììèðîâàíèÿ. Íå Smalltalk, êîíå÷íî, íî ÷åãî îæèäàòü îò ÿçûêà, ðàáîòàþùåãî ñ òàêîé
ãîëîâîêðóæèòåëüíîé ñêîðîñòüþ? Ñ++ — ýòî Cobol 90-õ, ïîëèòè÷åñêè âûäåðæàííûé ÿçûê, êîòîðûå
ãàðàíòèðóåò ôèíàíñèðîâàíèå âàøåãî ïðîåêòà âûñøèì ðóêîâîäñòâîì. À óæ åñëè Ñ++ äîñòàòî÷íî ÷àñòî
óïîìèíàåòñÿ â ïëàíå, ìîæíî íàäåÿòüñÿ íà óäâîåíèå áþäæåòà. Ýòî òîæå õîðîøî, ïîòîìó ÷òî íèêòî
òîëêîì íå óìååò îöåíèâàòü ïðîåêòû íà Ñ++ è óïðàâëÿòü èìè. À ÷òî êàñàåòñÿ èíñòðóìåíòàðèÿ — ãëàçà
ðàçáåãàþòñÿ, íå ïðàâäà ëè?
Äçûíü! Ïîñëåäíèé ýòàæ, âñå âûõîäÿò. Íî ïîçâîëüòå, ãäå æå «âñå»? Ëèôò ïî÷òè ïóñò. Ñ++ — ýòî íà
ñàìîì äåëå íå ñòîëüêî ÿçûê, ñêîëüêî èíñòðóìåíò äëÿ ñîçäàíèÿ âàøèõ ñîáñòâåííûõ ÿçûêîâ. Åãî
ýëåãàíòíîñòü çàêëþ÷àåòñÿ îòíþäü íå â ïðîñòîòå (ñëîâà Ñ++ è ïðîñòîòà ðåæóò ñëóõ ñâîèì ÿâíûì
ïðîòèâîðå÷èåì), à â åãî ïîòåíöèàëüíûõ âîçìîæíîñòÿõ. Çà êàæäîé óðîäëèâîé ïðîáëåìîé ïðÿ÷åòñÿ
êàêàÿ-íèáóäü óìíàÿ èäèîìà, èçÿùíûé ÿçûêîâîé ôèíò, áëàãîäàðÿ êîòîðîìó ïðîáëåìà òàåò ïðÿìî íà
ãëàçàõ. Ïðîáëåìà ðåøàåòñÿ òàê æå ýëåãàíòíî, êàê ýòî ñäåëàë áû íàñòîÿùèé ÿçûê òèïà Smalltalk èëè
Lisp, íî ïðè ýòîì âàø ïðîöåññîð íå äûìèòñÿ îò íàïðÿæåíèÿ, à íà Óîëë-Ñòðèò íå ðàñòóò àêöèè
ïðîèçâîäèòåëåé ÷èïîâ ïàìÿòè. Ñ++ — âîîáùå íå ÿçûê. Ýòî ìèðîâîççðåíèå èëè íàðêîòèê, ìåíÿþùèé
ñïîñîá ìûøëåíèÿ.
Íî âåðíåìñÿ ê ñëîâó «ýëåãàíòíûé». Â ïðîãðàììèðîâàíèè íà Ñ++ äåéñòâóåò ïåðåôðàçèðîâàííûé
ïðèíöèï Äàî: «×òîáû äîñòè÷ü èñòèííîé ýëåãàíòíîñòè, íóæíî îòêàçàòüñÿ îò ñòðåìëåíèÿ ê
ýëåãàíòíîñòè». Ñ++ âî ìíîãîì ïðåäñòàâëÿåò ñîáîé Ñ ñëåäóþùåãî ïîêîëåíèÿ. Íàïèñàííûå íà íåì
ïðîãðàììû ýôôåêòèâíî êîìïèëèðóþòñÿ è áûñòðî ðàáîòàþò. Îí îáëàäàåò î÷åíü òðàäèöèîííîé áëî÷íîé
ñòðóêòóðîé è ñîêðàùåííîé çàïèñüþ äëÿ ìíîãèõ ðàñïðîñòðàíåííûõ îïåðàöèé (íàïðèìåð, i++). Â íåì
åñòü ñâîè ñóùåñòâèòåëüíûå, ãëàãîëû, ïðèëàãàòåëüíûå è ñâîé æàðãîí:
cout << 17 << endl << flush;
Ðåâíèòåëè ÷àñòîòû ÿçûêà ÷àñòî íàïàäàþò íà Ñ++. Îíè ïîëàãàþò, ÷òî âûñøåå äîñòèæåíèå ñîâðåìåííîé
öèâèëèçàöèè — ÿçûê, ïîñòðîåííûé èñêëþ÷èòåëüíî èç àòîìîâ è ñêîáîê. Ïî ìíåíèþ ýòèõ òåððîðèñòîâ
îò ñèíòàêñèñà, åñëè ïðîñòóþ ïåðåìåííóþ ñ ïåðâîãî âçãëÿäà íåâîçìîæíî îòëè÷èòü îò âûçîâà ôóíêöèè
èëè ìàêðîñà — ýòî âîîáùå íå ÿçûê, à øàðëàòàíñòâî äëÿ ðàçâëå÷åíèÿ ïðàçäíîé òîëïû. Ê ñîæàëåíèþ,
òåîðèÿ ðàñõîäèòñÿ ñ ïðàêòèêîé. Â ðåàëüíîé æèçíè òîëïà ïëàòèò ëèøü çà òî, ÷òîáû âèäåòü ÿçûêè, â
êîòîðûõ ðàçíûå èäåè âûãëÿäÿò ïî-ðàçíîìó. «Ïðîñòûå è ïîñëåäîâàòåëüíûå» ÿçûêè íèêîãäà íå
ïîëüçîâàëèñü îñîáûì óñïåõîì çà ñòåíêàìè àêàäåìèé, à ÿçûêè ñ áëî÷íîé ñòðóêòóðîé îâëàäåëè ìàññàìè.
Ñòîèò ëè ýòîìó óäèâëÿòüñÿ? Âåäü êîìïüþòåðíûå ÿçûêè ïðèõîäèòñÿ èçó÷àòü è çàïîìèíàòü, à äëÿ ýòîãî
èñïîëüçóåòñÿ òî æå ñåðîå âåùåñòâî, ñ ïîìîùüþ êîòîðîãî ìû èçó÷àåì è çàïîìèíàåì åñòåñòâåííûå
ÿçûêè. Ïîïðîáóéòå-êà íàçâàòü õîòÿ áû îäèí åñòåñòâåííûé ÿçûê áåç ñóùåñòâèòåëüíûõ, ãëàãîëîâ è
ñêîáîê! ß áû íå ðèñêíóë. Âñå íàøè ïîçíàíèÿ â ëèíãâèñòèêå ãîâîðÿò î òîì, ÷òî ýòè «ïëîõèå»
îñîáåííîñòè òîëüêî óñêîðÿþò èçó÷åíèå êîìïüþòåðíîãî ÿçûêà è äåëàþò åãî áîëåå ïîíÿòíûì. i++ âî
âñåõ îòíîøåíèÿõ äåéñòâèòåëüíî ïîíÿòíåå, ÷åì i:=i+1, à x=17+29 ÷èòàåòñÿ ëó÷øå, íåæåëè (setq
x(+17, 29)). Ðå÷ü èäåò íå î ñòðîåíèè êîìïüþòåðíîãî ÿçûêà, à ñêîðåå î íàøåì ñîáñòâåííîì
ñòðîåíèè. Âñå óðîäñòâà Ñ++ — ýòî â îñíîâíîì íàøè óðîäñòâà. Êîãäà âû íàó÷èòåñü ïîíèìàòü è ëþáèòü
åãî ñòðàííîñòè, êîãäà ïåðåñòàíåòå áåñïîêîèòüñÿ î ìàòåìàòè÷åñêîé ñòðîéíîñòè, áóäåò ñäåëàí âàø
ïåðâûé øàã ê äîñòèæåíèþ ýëåãàíòíîñòè â Ñ++.
Ñ++ íàðÿäó ñ Lisp, Smalltalk è äðóãèìè äèíàìè÷åñêèìè ÿçûêàìè (â îòëè÷èå îò Ñ) îáëàäàåò ñðåäñòâàìè
äëÿ íèçêîóðîâíåâûõ ìàíèïóëÿöèé ñ êîìïüþòåðîì. Âû ìîæåòå ñîçäàòü ñâîé ñîáñòâåííûé òèï äàííûõ è
ïîäñóíóòü åãî êîìïèëÿòîðó òàê, ÷òîáû îí ïðèíÿë ýòîò òèï çà âñòðîåííûé. Âû ìîæåòå óïðàâëÿòü
âûçîâàìè ñâîèõ ôóíêöèé, îáðàùåíèÿìè ê ïåðåìåííûì êëàññîâ, âûäåëåíèåì è îñâîáîæäåíèåì ïàìÿòè,
èíèöèàëèçàöèåé è óäàëåíèåì îáúåêòîâ — è âñå ýòî (â îñíîâíîì) ïðîèñõîäèò áåç ïîòåðè
ýôôåêòèâíîñòè èëè áåçîïàñíîñòè òèïîâ. Íî â îòëè÷èå îò äðóãèõ ÿçûêîâ, åñëè ýòà ñèëà áóäåò ïðèìåíåíà
íåïðàâèëüíî, ïðîãðàììà íà Ñ++ «ãðîõíåòñÿ». À åñëè óñòîèò ïðîãðàììà, ãðîõíóòñÿ âàøè êîëëåãè-
ïðîãðàììèñòû — åñëè âû íå ïðèäóìàåòå, êàê ïîÿñíèòü ñâîè íàìåðåíèÿ è èñïîëüçîâàòü ïðàâèëüíóþ
èäèîìó äëÿ îñîáåííî ñëîæíûõ ìîìåíòîâ. Êàê èçâåñòíî, Äåäàë ñî ñâîèì ñûíîì Èêàðîì áåæàë è
çàòî÷åíèÿ íà Êðèòå ñ ïîìîùüþ êðûëüåâ, ñäåëàííûõ èç ïåðüåâ è âîñêà. Äåäàë, ãëàâíûé àðõèòåêòîð è
èçîáðåòàòåëü, ñïîêîéíî ïîðõàë ãäå-òî âíèçó. Åãî áåçðàññóäíûé ñûí ïîäíÿëñÿ ñëèøêîì âûñîêî ê
ñîëíöó è óïàë â ìîðå. Õììì… Íåò, ïîæàëóé, àíàëîãèÿ ïîëó÷èëàñü íåóäà÷íàÿ. Âåäü èìåííî Äåäàë
ïîñòðîèë Ëàáèðèíò — òàêîé ñëîæíûé, ÷òî â ïîïûòêàõ âûáðàòüñÿ èç íåãî ëþäè ëèáî óìèðàëè, ëèáî
ïîïàäàëè íà îáåä ê Ìèíîòàâðó. Ìîæåò, ïîïðîáóåì áîëåå ñîâðåìåííóþ àíàëîãèþ? Èñïîëüçóÿ

15
íèçêîóðîâíåâûå âîçìîæíîñòè Ñ++, âû äåéñòâóåòå, êàê ñóðîâûé äåòåêòèâ ñ åãî ñàêðàìåíòàëüíîé
ôðàçîé: «Äîâåðüñÿ ìíå — ÿ çíàþ, ÷òî äåëàþ». Êîìïèëÿòîð çàêàòûâàåò ãëàçà è áåçìîëâíî ïîä÷èíÿåòñÿ.
Ñ++ èíòðèãóåò ñâîèìè ÿâíûìè ïðîòèâîðå÷èÿìè. Åãî ãèáêîñòü ëåãêî ïðåâðàùàåòñÿ â ãëàâíûé èñòî÷íèê
îøèáîê. Çà âîçìîæíîñòè åãî ðàñøèðåíèÿ íå ïðèõîäèòñÿ ðàñïëà÷èâàòüñÿ ñêîðîñòüþ èëè îáúåìîì êîäà.
Îí ýëåãàíòåí â îäíèõ ðóêàõ è îïàñåí â äðóãèõ, ïðîñò è ñëîæåí îäíîâðåìåííî. Ïîñëå íåñêîëüêèõ ëåò
ðàáîòû âû òàê è íå ìîæåòå ðåøèòü, âîñõèùàòüñÿ èì èëè ïðîêëèíàòü. Äà, íàñòîÿùèé çíàòîê ïîíèìàåò
âñå êîíöåïöèè, ëåæàùèå â îñíîâå ÿçûêà è ñêëîíÿþùèå ÷àøó âåñîâ â åãî ïîëüçó. Ýòè êîíöåïöèè íå
âèäíû ñ ïåðâîãî âçãëÿäà; ÷òîáû ïîíÿòü èõ, íåîáõîäèìî â òå÷åíèå íåñêîëüêèõ ëåò ïûòàòüñÿ ðåøàòü
ñîâåðøåííî ðàçíûå çàäà÷è. Íåêîòîðûå àðõèòåêòóðíûå ïàðàäèãìû ëó÷øå âñåãî ñîîòâåòñòâóþò
êîíêðåòíûì ÿçûêîâûì ðåøåíèÿì. Èõ íåïðàâèëüíîå ñî÷åòàíèå îáåðíåòñÿ õàîñîì, à ïðàâèëüíîå —
ýëåãàíòíîñòüþ.
Òðè âåëèêèå èäåè Ñ++
Î íåòðèâèàëüíîì èñïîëüçîâàíèè C++ íàïèñàíî òàê ìíîãî, ÷òî ÿ äàæå íå çíàþ, ñ ÷åãî íà÷àòü. Âàì
êîãäà-íèáóäü ïðèõîäèëîñü âèäåòü ñòåðåîãðàììû? Ñ ïåðâîãî âçãëÿäà îíè ïîõîæè íà ñëó÷àéíûé óçîð, íî
ïîñëå ìåäëåííîãî è âíèìàòåëüíîãî ðàçãëÿäûâàíèÿ íà íèõ ïðîÿâëÿåòñÿ ñëîí, ñïèðàëü èëè ÷òî-íèáóäü
åùå. ×òîáû óâèäåòü ñìûñë â òî÷êàõ è ïÿòíàõ, íóæíî ðàññìàòðèâàòü èõ â êîíòåêñòå îáúåäèíÿþùåé
òåìû. Èìåííî çäåñü êðîåòñÿ îäíî èç ñàìûõ áîëüøèõ ðàçî÷àðîâàíèé ïðè èçó÷åíèè àðõèòåêòóðû è èäèîì
C++. Ñíà÷àëà êàæåòñÿ, ÷òî ïåðåä âàìè — îãðîìíàÿ êó÷à ðàçðîçíåííûõ ïðèåìîâ è íè îäíîãî ïðàâèëà
òîãî, êàê èìè ïîëüçîâàòüñÿ. Ýòà êíèãà íàó÷èò âàñ «âèäåòü ñëîíà». Ñóùåñòâóåò ìíîæåñòâî
êëàññèôèêàöèé íåòðèâèàëüíûõ àñïåêòîâ C++, íî ÿ ðàçäåëèë èõ íà íåñêîëüêî ïðîñòûõ òåì:
• Êîñâåííûå îáðàùåíèÿ.
• Ãîìîìîðôíûå èåðàðõèè êëàññîâ.
• Ïðîñòðàíñòâà ïàìÿòè.
 îñíîâå êàæäîé òåìû ëåæèò êîíêðåòíûé ñèíòàêñèñ è ñðåäñòâà C++, è èõ ñîâìåñòíîå ïðèìåíåíèå
ïîçâîëÿåò ðåøàòü ñàìûå ðàçíûå çàäà÷è. Ñóùåñòâóåò ìíîãî äðóãèõ ïðèåìîâ è ïðèíöèïîâ, êîòîðûå òîæå
ñòîèëî áû âêëþ÷èòü â ýòó êíèãó, íî ýòè òðè êàòåãîðèè ïîìîãàþò îðãàíèçîâàòü î÷åíü áîëüøîå
êîëè÷åñòâî òåì â ëîãè÷åñêè ñòðîéíóþ ñòðóêòóðó.
 ïåðâîé ÷àñòè ïðèâåäåí îáçîð ìíîãèõ âàæíûõ àòòðàêöèîíîâ ñèíòàêñè÷åñêîãî öèðêà C++. Íàïðèìåð,
ìíîãèå ïðîãðàììèñòû C++ íå èìåþò áîëüøîãî îïûòà ðàáîòû ñ ïåðåãðóæåííûìè îïåðàòîðàìè è ëèøü
òåîðåòè÷åñêè çíàþò, êàê îíè ïðèìåíÿþòñÿ. Îêàçûâàåòñÿ, áîëüøèíñòâî ïðîãðàììèñòîâ íèêîãäà íå
èñïîëüçóåò øàáëîíû èëè îáðàáîòêó èñêëþ÷åíèé è ëèøü íåìíîãèå óìåþò ïîëüçîâàòüñÿ ïîòîêàìè
ââîäà/âûâîäà çà ðàìêàìè ïðîñòåéøèõ îáðàùåíèé ê îáúåêòàì cout è cin.  ÷àñòè 1 ñòàðàþñü
âûðîâíÿòü óðîâíè ïîäãîòîâêè ÷èòàòåëåé, çàïîëíèòü ïðîáåëû â âàøèõ çíàíèÿõ C++ è ïîäãîòîâèòüñÿ ê
èãðå. ×àñòü 1 ìîæíî ÷èòàòü îò êîðêè äî, áåãëî ïðîñìàòðèâàòü èëè ïðîïóñêàòü öåëûå ðàçäåëû â
çàâèñèìîñòè îò òîãî, íàñêîëüêî õîðîøî âû çíàêîìû ñ íþàíñàìè C++.
Òåðìèí êîñâåííîå îáðàùåíèå (indirection) îòíîñèòñÿ ê ðàçíûì êîíêðåòíûì òåìàì, îäíàêî âåçäå
èñïîëüçóåòñÿ îäíà è òà æå êîíöåïöèÿ: êëèåíòñêèé îáúåêò îáðàùàåòñÿ ñ çàïðîñîì ê äðóãîìó îáúåêòó,
êîòîðûé, â ñâîþ î÷åðåäü, ïîðó÷àåò ðàáîòó òðåòüåìó îáúåêòó. Êîñâåííîñòü ñâÿçàíà ñî ñðåäíèì îáúåêòîì
â öåïî÷êå. Èíîãäà ãîäèòñÿ ñëûøàòü, ÷òî ýòî îïðåäåëåíèå ïî÷òè ñîâïàäàåò ñ îïðåäåëåíèåì
äåëåãèðîâàíèÿ (delegation), îäíîãî èç êðàåóãîëüíûõ êàìíåé îáúåêòíî-îðèåíòèðîâàííîãî
ïðîãðàììèðîâàíèÿ. Òåì íå ìåíåå, â C++ èäèîìû, èñïîëüçóåìûå ñ ýòîé êîíöåïöèåé, è åå ÿçûêîâàÿ
ïîääåðæêà âûõîäÿò äàëåêî çà ðàìêè òîãî, ÷òî ñ÷èòàåòñÿ äåëåãèðîâàíèåì â äðóãèõ ÿçûêàõ.  ýòîé êíèãå
÷àñòî èñïîëüçóåòñÿ òåðìèí óêàçàòåëü (pointer); âû âñòðåòèòå åãî â êàæäîé ãëàâå. Óêàçàòåëè C++
ñïîñîáíû íà ìíîãîå. Îíè ìîãóò îïðåäåëèòü, ãäå â ïàìÿòè, íà äèñêå èëè â ñåòè íàõîäèòñÿ îáúåêò, íà
êîòîðûé îíè ññûëàþòñÿ; êîãäà îí óíè÷òîæàåòñÿ; èçìåíÿåòñÿ ëè îí èëè äîñòóïåí òîëüêî äëÿ ÷òåíèÿ; è
äàæå òî, ñóùåñòâóåò ëè îáúåêò èëè ïðîñòî ïðåäñòàâëÿåò ñîáîé íåêóþ îáëàñòü â àáñòðàêòíîì
ïðîñòðàíñòâå ïàìÿòè — è âñå ýòî ïðîèñõîäèò áåç àêòèâíîãî ó÷àñòèÿ ñàìîãî îáúåêòà, êîòîðûé ìîæåò
íè÷åãî íå çíàòü îá ýòèõ íèçêîóðîâíåâûõ îïåðàöèÿõ. Âîçìîæíîñòè, ÷òî è ãîâîðèòü, âïå÷àòëÿþùèå,
îäíàêî îíè îñíîâàíû íà íåñêîëüêèõ î÷åíü ïðîñòûõ èäèîìàõ.
Î ïðîåêòèðîâàíèè èåðàðõèè êëàññîâ ãîâîðèëè âñå êîìó íå ëåíü — îäíè ïî äåëó, äðóãèå áîëòàëè îá
«èìèòàöèè îáúåêòîâ ðåàëüíîãî ìèðà». Áîëüøèíñòâî àðãóìåíòîâ â ðàâíîé ñòåïåíè îòíîñèòñÿ ê ëþáîìó
îáúåêòíî-îðèåíòèðîâàííîìó ÿçûêó, è ÿ âîâñå íå íàìåðåí çàõëàìëÿòü êíèãó ïî C++ ñâîèìè ëè÷íûìè

16
âçãëÿäàìè íà îáúåêòíî-îðèåíòèðîâàííûé äèçàéí. Òåì íå ìåíåå, îäèí êîíêðåòíûé òèï íàñëåäîâàíèÿ —
ãîìîìîðôíîå íàñëåäîâàíèå (homomorphic derivation) — îêàçûâàåòñÿ èñêëþ÷èòåëüíî ïîëåçíûì â
ñî÷åòàíèè ñî ñïåöèôè÷åñêèìè ñðåäñòâàìè C++.  ãîìîìîðôíîé èåðàðõèè âñå ïðîèçâîäíûå êëàññû
ïîëó÷àþò ñâîé îòêðûòûé èíòåðôåéñ îò íåêîòîðîãî áàçîâîãî êëàññà-ïðåäêà. Êàê ïðàâèëî, «ìàòü âñåõ
áàçîâûõ êëàññîâ» äåâñòâåííî ÷èñòà — îíà íå ñîäåðæèò íè îäíîé ïåðåìåííîé, à âñå åå ôóíêöèè
ÿâëÿþòñÿ ÷èñòî âèðòóàëüíûìè.  C++ ñ ýòîé êîíöåïöèåé àññîöèèðóþòñÿ ìíîãèå ïîëåçíûå èäèîìû
ïðîåêòèðîâàíèÿ è ïðîãðàììèðîâàíèÿ.
Çà êîíöåïöèåé ïðîñòðàíñòâà ïàìÿòè (memory space) êðîåòñÿ íå÷òî áîëüøåå, ÷åì îáû÷íîå óïðàâëåíèå
ïàìÿòüþ. Ïåðåãðóæàÿ â C++ îïåðàòîðû new è delete, âû îïðåäåëÿåòå, ãäå ñîçäàþòñÿ îáúåêòû è êàê
îíè óíè÷òîæàþòñÿ. Êðîìå òîãî, ìîæíî ñîçäàâàòü àáñòðàêòíûå êîëëåêöèè, â êîòîðûõ íå âñåãäà ïîíÿòíî,
ñ ÷åì âû èìååòå äåëî — ñ íàñòîÿùèì îáúåêòîì èëè ñ àáñòðàêöèåé. Íà ãîðèçîíòå óæå âèäíû êîíòóðû
íîâûõ ðàñïðåäåëåííûõ îáúåêòíî-îðèåíòèðîâàííûõ ñòðóêòóð, ðàçðàáîòàííûõ òàêèìè ôèðìàìè, êàê
Microsoft, Apple è Taligent. Ïðàâäà, âàì ïðèäåòñÿ ïåðåñìîòðåòü íåêîòîðûå áàçîâûå ïðåäñòàâëåíèÿ î
òîì, ãäå íàõîäÿòñÿ îáúåêòû è êàê îíè ïåðåìåùàþòñÿ â äðóãîå ìåñòî — âñå ýòè òåìû ÿ âûäåëèë â
êàòåãîðèþ ïðîñòðàíñòâ ïàìÿòè. Ïðîñòðàíñòâà ïàìÿòè ïîçâîëÿþò îïðåäåëèòü òèï îáúåêòà âî âðåìÿ
âûïîëíåíèÿ ïðîãðàììû — âîçìîæíîñòü, êîòîðîé äî îáèäíîãî íå õâàòàåò â C++. Êîíå÷íî, ìû
ïîãîâîðèì è îá óïðàâëåíèè ïàìÿòüþ, íî ýòèì äåëî íå îãðàíè÷èòñÿ.
Êàê ÷èòàòü ýòó êíèãó
Ïåðåä âàìè — íå ðóêîâîäñòâî ñ ãîòîâûìè ðåöåïòàìè äëÿ êîíêðåòíûõ ñèòóàöèé. Ñêîðåå ýòî ñáîðíèê
òâîð÷åñêèõ èäåé è ãîëîâîëîìîê. Åñëè ê êîíöó êíèãè âû ïî÷óâñòâóåòå, ÷òî âàø àðñåíàë ïðèåìîâ
ïðîãðàììèðîâàíèÿ íà C++ ðàñøèðèëñÿ, çíà÷èò, ÿ äîñòèã ñâîåé öåëè, à ó÷èòü âàñ, êîãäà è êàê
ïîëüçîâàòüñÿ ýòèìè ïðèåìàìè, ÿ íå ñòàíó.
Ìàòåðèàë êàæäîé îòäåëüíîé ãëàâû íåâîçìîæíî â ïîëíîé ìåðå ïîíÿòü áåç ïðåäâàðèòåëüíîãî çíàêîìñòâà
ñî âñåìè îñòàëüíûìè ãëàâàìè. È âñå æå ÿ ïðèëîæèë ìàêñèìóì óñèëèé, ÷òîáû ìàòåðèàë ëþáîé ãëàâû
áûë ïîëåçåí íåìåäëåííî ïîñëå çíàêîìñòâà ñ íåé è ÷òîáû ãëàâû ëîãè÷åñêè ñëåäîâàëè äðóã çà äðóãîì, à
íàø âîîáðàæàåìûé ñëîí âûðèñîâûâàëñÿ ïîñòåïåííî — áèâíè, óøè, õîáîò è ò. ä. Ïîñëå ïðî÷òåíèÿ
êíèãà ìîæåò ïðèãîäèòüñÿ â êà÷åñòâå ñïðàâî÷íèêà — ÷òî-òî âðîäå ëè÷íîé è î÷åíü êðàòêîé
ýíöèêëîïåäèè ïðèåìîâ ïðîãðàììèðîâàíèÿ è èäèîì C++.
Çà ìíîãèå ãîäû èçó÷åíèÿ è èñïîëüçîâàíèÿ C++ ÿ óçíàë, ÷òî äàæå ó îïûòíûõ ïðîãðàììèñòîâ â
ïîçíàíèÿõ âñòðå÷àþòñÿ ïðîáåëû; â îñòàâøåìñÿ ìàòåðèàëå ÷àñòè ÿ ïîñòàðàþñü âûðîâíÿòü óðîâåíü
ïîäãîòîâêè âñåõ ÷èòàòåëåé. Ýòî íå âñòóïèòåëüíîå îïèñàíèå ÿçûêà, à ñêîðåå êðàòêàÿ ñâîäêà òåì,
êîòîðûå áóäóò èñïîëüçîâàíû â ïîñëåäóþùèõ ãëàâàõ. Â ãëàâå 2 ìû ñòðåìèòåëüíî ïðîáåæèìñÿ ïî
íåêîòîðûì îñîáåííîñòÿì ÿçûêà. Ãëàâà 3 ïîñâÿùåíà øàáëîíàì — ïîñòåïåííî ýòà òåìà ñòàíîâèòñÿ âñå
áîëåå âàæíîé, ïîñêîëüêó øàáëîíû ïîääåðæèâàþòñÿ âî âñå áîëüøåì ÷èñëå êîìïèëÿòîðîâ.  ãëàâå 4
ðàññìàòðèâàåòñÿ îáðàáîòêà èñêëþ÷åíèé íà îñíîâå ðåêîìåíäîâàííîãî ñòàíäàðòà ANSI è ïðèâîäèòñÿ
ïàðà çàìå÷àíèé î íåñòàíäàðòíûõ èñêëþ÷åíèÿõ, âñòðå÷àþùèõñÿ â ðåàëüíîì ìèðå.
×àñòü 2 ïîñâÿùåíà ðàçíûì òèïàì óêàçàòåëåé — îò ãëóïûõ äî ãåíèàëüíûõ. Íà ýòîì ôóíäàìåíòå
ïîñòðîåíà âñÿ êíèãà, è ÿ óâåðåí, ÷òî ýòè ñâåäåíèÿ áóäóò ïîëåçíû ëþáîìó ÷èòàòåëþ.
 ÷àñòè 3 ðàññìàòðèâàþòñÿ ñòðóêòóðà è ðåàëèçàöèÿ òèïîâ è èåðàðõèé êëàññîâ â C++. Îñíîâíîå
âíèìàíèå óäåëåíî îäíîìó èç ÷àñòíûõ ñëó÷àåâ — ãîìîìîðôíûì èåðàðõèÿì êëàññîâ. Çàîäíî ìû
ïîãîâîðèì îá îáúåêòàõ êëàññîâ, ïðåäñòàâèòåëÿõ è äðóãèõ ëþáîïûòíûõ òåìàõ. Áîëüøèíñòâó ÷èòàòåëåé
ñòîèò ïðî÷èòàòü òðåòüþ ÷àñòü îò íà÷àëà äî êîíöà, íî íèêòî íå çàïðåùàåò âàì ïðîñìîòðåòü åå è
îòîáðàòü òåìû ïî ñâîåìó âêóñó. È õîòÿ âû áóäåòå ïîëàãàòü, ÷òî çíàåòå îá óêàçàòåëÿõ âñå íà ñâåòå, îíè
ñîâåðøåííî íåîæèäàííî ñíîâà âîçíèêíóò â êîíòåêñòå ãîìîìîðôíûõ èåðàðõèé.
 ÷àñòè 4 íàñ ïîäæèäàåò ñàìàÿ óæàñíàÿ òåìà C++ — óïðàâëåíèå ïàìÿòüþ. Óðîâåíü èçëîæåíèÿ
ìåíÿåòñÿ îò ïðèìèòèâíîãî äî íîðìàëüíîãî è ñâåðõñëîæíîãî, íî îñíîâíîå âíèìàíèå óäåëÿåòñÿ òåì
ïðîáëåìàì, êîòîðûå ìîãóò âîçíèêíóòü ïðè ïðîãðàììèðîâàíèè íà C++, è èõ âîçìîæíûì ðåøåíèÿì íà
áàçå ðàçíûõ ÿçûêîâûõ ñðåäñòâ. Ëè÷íî ÿ ñ÷èòàþ, ÷òî íà÷àëüíûå ãëàâû ýòîé ÷àñòè àáñîëþòíî
íåîáõîäèìû äëÿ ñ÷àñòëèâîé è ïîëíîöåííîé æèçíè â C++, íî åñëè âàñ, äîïóñòèì, ñîâåðøåííî íå
èíòåðåñóåò ïðîöåññ ñáîðêè ìóñîðà — îñòàâüòå ïîñëåäíþþ ïàðó ãëàâ è çàéìèòåñü ÷åì-íèáóäü áîëåå
ïîëåçíûì äëÿ îáùåñòâà.

17
Íåñêîëüêî ñëîâ î ñòèëå ïðîãðàììèðîâàíèÿ
Âîò ýòè íåñêîëüêî ñëîâ: ñòèëü ïðîãðàììèðîâàíèÿ ìåíÿ íå âîëíóåò. ß äîñòàòî÷íî êðàòîê? Åñëè õîòÿ áû
ïîëîâèíà âðåìåíè, èçðàñõîäîâàííîãî íà ïðàâèëüíóþ ðàññòàíîâêó ôèãóðíûõ ñêîáîê, òðàòèëàñü íà
îáäóìûâàíèå ïðîãðàììû èëè åùå ëó÷øå — íà îáùåíèå ñ ïîëüçîâàòåëÿìè, òî âñÿ îòðàñëü ðàáîòàëà áû
íàìíîãî ýôôåêòèâíåå. Êîíå÷íî, åäèíñòâî ñòèëÿ — âåùü õîðîøàÿ, íî ÿ åùå íå âèäåë êíèãè èëè
ðóêîâîäñòâà ïî ñòèëþ, êîòîðûå áû ñòîèëè äàæå ÷àñîâîãî ñîáðàíèÿ ãðóïïû â íà÷àëå ïðîåêòà. Ê òîìó æå
íè îäíà êíèãà èëè ðóêîâîäñòâî ïî ñòèëþ íå ïðåâðàòÿò êîä íåàêêóðàòíîãî ïðîãðàììèñòà â íå÷òî
îñìûñëåííîå.  ñóùíîñòè, ñòèëü ÷àñòî èñïîëüçóåòñÿ êàê îïðàâäàíèå íåäîñòàòêà âíèìàíèÿ ê ñàìîé
ïðîãðàììå. Íàêîíåö, ÿ åùå íå âèäåë, ÷òîáû â ñïîðàõ î ñòèëå îäèí ïðîãðàììèñò â ÷åì-òî óáåäèë
äðóãîãî, ïîýòîìó ëþáûå äèñêóññèè íà ýòó òåìó ñ÷èòàþ áåñïîëåçíîé òðàòîé âðåìåíè.
Ó ìåíÿ åñòü ñâîè ñîáñòâåííûå ïðèíöèïû è ñâîé ñòèëü, íî â îñíîâíîì ÿ ñîáèðàþñü îòêàçàòüñÿ îò ñâîåãî
ïóòè è ïîíåìíîãó ïîëüçîâàòüñÿ âñåìè ñòèëÿìè, ñ êîòîðûìè ìíå ïðèõîäèëîñü âñòðå÷àòüñÿ. Êíèãà
ïîñâÿùåíà ÿçûêîâûì èäèîìàì, à íå ðàñïîëîæåíèþ ôèãóðíûõ ñêîáîê èëè ðåãèñòðó ñèìâîëîâ. Íàäåþñü,
ìîå ðåøåíèå áóäåò ðàçäðàæàòü âñåõ ÷èòàòåëåé â ðàâíîé ìåðå.
ß òàêæå âåñüìà âîëüíî îáîøåëñÿ ñ ïîäñòàâëÿåìûìè (inline) ôóíêöèÿìè êëàññîâ, îñîáåííî ñ
âèðòóàëüíûìè.  êàíîíè÷åñêîì âàðèàíòå ïîäñòàâëÿåìûå ôóíêöèè äîëæíû âûãëÿäåòü ñëåäóþùèì
îáðàçîì:
class Foo {
public:
void MemberFn();
};
inline void Foo::MemberFn()
{
...
}
 ìîåé êíèãå ýòîò ôðàãìåíò áóäåò âûãëÿäåòü èíà÷å:
class Foo {
public:
void MemberFnO {...};
};
ß îôîðìëÿë êàê ïîäñòàâëÿåìûå äàæå âèðòóàëüíûå ôóíêöèè êëàññîâ, õîòÿ îäíè êîìïèëÿòîðû
îòâåðãàþò òàêîé ñèíòàêñèñ, à äðóãèå îáðàáàòûâàþò åãî íåïðàâèëüíî. Äåëàëîñü ýòî äëÿ ýêîíîìèè ìåñòà.
Åñëè áû òåêñòû âñåõ ïîäñòàâëÿåìûõ ôóíêöèé ïðèâîäèëèñü îòäåëüíî, êíèãà çàìåòíî âûðîñëà áû â
ðàçìåðàõ, à ðàçðûâû ñòðàíèö ÷àùå ïðèõîäèëèñü íà ñåðåäèíó ëèñòèíãà. Òàê ÷òî íå îòíîñèòåñü ê
ïîäñòàâëÿåìûì ôóíêöèÿì ñëèøêîì ñåðüåçíî.
Ñàäèòåñü â ëþáèìîå êðåñëî, çàâîäèòå õîðîøóþ ìóçûêó, ñòàâüòå ïîä ðóêó ÷àøêó ÷àÿ è ïîïûòàéòåñü
ïîëó÷èòü óäîâîëüñòâèå!


Ñèíòàêñèñ Ñ++
Çà ãîäû ïðåïîäàâàíèÿ C++ ÿ óçíàë, ÷òî ïîäàâëÿþùåå áîëüøèíñòâî ïðîãðàììèñòîâ C++ (âêëþ÷àÿ
ñàìûõ îïûòíûõ) ðåäêî ïîëüçóåòñÿ íåêîòîðûìè âîçìîæíîñòÿìè ÿçûêà. Êîíå÷íî, äåëî ýòî ñóãóáî
èíäèâèäóàëüíîå, íî ïðè âñåé ñëîæíîñòè è ãëóáèíå C++ íåáîëüøîé îáçîð íå ïîâðåäèò íèêîìó. Â ýòîé è
äâóõ ñëåäóþùèõ ãëàâàõ ÿ ïîñòàðàþñü âûðîâíÿòü óðîâåíü ïîäãîòîâêè ÷èòàòåëåé ïåðåä òåì, êàê ïå-
ðåõîäèòü ê äåéñòâèòåëüíî èíòåðåñíûì òåìàì. Ýòà ãëàâà íå çàìåíèò Annotated Reference Manual èëè
äðóãîå ñïðàâî÷íîå ðóêîâîäñòâî — âû íå íàéäåòå â íåé ïîëíîé ñïåöèôèêàöèè ÿçûêà. ß ëèøü
ðàññìîòðþ íåêîòîðûå ÿçûêîâûå ñðåäñòâà, êîòîðûå ÷àñòî ïîíèìàþòñÿ íåâåðíî èëè íå ïîíèìàþòñÿ
âîâñå. Ïðèäåðæèòå øëÿïó è ïðèãîòîâüòåñü ê ñòðåìèòåëüíîìó îáëåòó ñèíòàêñèñà C++!
Ïåðåìåííûå è êîíñòàíòû
Áîëòîâíþ î òîì, ÷òî òàêîå ïåðåìåííûå è äëÿ ÷åãî îíè íóæíû, ïðîïóñêàåì. Íàøåãî âíèìàíèÿ
çàñëóæèâàþò äâå òåìû: êîíñòàíòíîñòü è ñðàâíåíèå äèíàìè÷åñêèõ îáúåêòîâ ñî ñòåêîâûìè.
const
Êëþ÷åâîå ñëîâî const, êîòîðîå â ðàçíûõ êîíòåêñòàõ ïðèíèìàåò ðàçíûå çíà÷åíèÿ, îäíî èç ñàìûõ
èíôîðìàòèâíûõ â C++. Äà, ìåæäó ýòèìè çíà÷åíèÿìè åñòü êîå-÷òî îáùåå, íî âàì âñå ðàâíî ïðèäåòñÿ
çàïîìíèòü âñå êîíêðåòíûå ñëó÷àè.
Êîíñòàíòíûå ïåðåìåííûå
Åñëè ïåðåìåííàÿ îáúÿâëåíà ñ êëþ÷åâûì ñëîâîì const, çíà÷èò, îíà íå äîëæíà ìåíÿòüñÿ. Ïîñëå
îïðåäåëåíèÿ êîíñòàíòíîé ïåðåìåííîé âû óæå íå ñìîæåòå èçìåíèòü åå çíà÷åíèå èëè ïåðåäàòü åå â
êà÷åñòâå àðãóìåíòà ôóíêöèè, êîòîðàÿ íå ãàðàíòèðóåò åå íåèçìåííîñòè. Ðàññìîòðèì ïðîñòîé ïðèìåð ñ
êîíñòàíòíîé öåëîé ïåðåìåííîé.
const int j = 17; // Öåëàÿ êîíñòàíòà
j = 29; // Íåëüçÿ, çíà÷åíèå íå äîëæíî ìåíÿòüñÿ
const int i; // Íåëüçÿ, îòñóòñòâóåò íà÷àëüíîå çíà÷åíèå
Òðåòüÿ ñòðîêà íåâåðíà, ïîñêîëüêó â íåé êîìïèëÿòîðó ïðåäëàãàåòñÿ îïðåäåëèòü ñëó÷àéíóþ ïåðåìåííóþ,
êîòîðóþ íèêîãäà íå óäàñòñÿ èçìåíèòü, — ýòàêèé ñòðàííûé ãåíåðàòîð ñëó÷àéíûõ öåëûõ êîíñòàíò.
Âîîáùå ãîâîðÿ, âû ñîîáùàåòå êîìïèëÿòîðó, êàêîé êîíñòðóêòîð îí äîëæåí èñïîëüçîâàòü â êîíêðåòíîì
ñëó÷àå. Åñëè áû ïåðåìåííàÿ i îòíîñèëàñü ê íåòðèâèàëüíîìó êëàññó, òî ïðè îáúÿâëåíèè êîíñòàíòíîãî
ýêçåìïëÿðà ïðèøëîñü áû ÿâíî óêàçàòü êîíñòðóêòîð è åãî àðãóìåíòû. int — âûðîæäåííûé ñëó÷àé,
ïîñêîëüêó íà ñàìîì äåëå const int j=17; — òî æå, ÷òî è int j(17).
Íî âîò êîìïèëÿòîð óçíàë, ÷òî íå÷òî äîëæíî áûòü êîíñòàíòíûì. Îí ïðîñûïàåòñÿ è íà÷èíàåò èñêàòü
îøèáêè — íå òîëüêî ôàêòè÷åñêèå, íî è ïîòåíöèàëüíûå. Êîìïèëÿòîð íå ðàçðåøèò èñïîëüçîâàòü âàøå
êîíñòàíòíîå íå÷òî â ëþáîì íåêîíñòàíòíîì êîíòåêñòå, äàæå åñëè øåñòèëåòíèé ðåáåíîê ðàçáåðåòñÿ â
ïðîãðàììå è äîêàæåò, ÷òî â íåé íåò íè îäíîé îøèáêè.
const i = 17;
int& j = 1; // Íåëüçÿ, ïîòîìó ÷òî ïîçäíåå j ìîæåò èçìåíèòüñÿ
2

20
Íå âàæíî, áóäåòå ëè âû èçìåíÿòü âåëè÷èíó, íà êîòîðóþ ññûëàåòñÿ j. Êîìïèëÿòîð ïðåäïîëàãàåò, ÷òî
âàì çàõî÷åòñÿ ýòî ñäåëàòü, è íà âñÿêèé ñëó÷àé óñòðàíÿåò èñêóøåíèå. Èíà÷å ãîâîðÿ, êîíñòàíòíîñòü —
ñâîéñòâî ïåðåìåííîé, à íå äàííûõ, ïîýòîìó íåêîíñòàíòíàÿ ïåðåìåííàÿ íå ìîæåò ññûëàòüñÿ íà
êîíñòàíòíóþ âåëè÷èíó.
const è #define
Äâå ñëåäóþùèå ñòðîêè íå ýêâèâàëåíòíû:
const int i = 17;
#define i 17;
 ïåðâîé ñòðîêå îïðåäåëÿåòñÿ ïåðåìåííàÿ, çàíèìàþùàÿ íåêîòîðóþ îáëàñòü ïàìÿòè, à âî âòîðîé —
ìàêðîñ. Îáû÷íî îòëè÷èÿ íåñóùåñòâåííû, åñëè íå ñ÷èòàòü îäíîãî-äâóõ ëèøíèõ òàêòîâ, çàòðà÷åííûõ íà
êàæäîå îáðàùåíèå ê êîíñòàíòíîé ïåðåìåííîé. Îäíàêî åñëè ïåðåìåííàÿ ÿâëÿåòñÿ ãëîáàëüíîé è
ïðèíàäëåæèò íåòðèâèàëüíîìó êëàññó ñî ñâîèì êîíñòðóêòîðîì, ñèòóàöèÿ ðåçêî ìåíÿåòñÿ.
Äîïîëíèòåëüíûå ñâåäåíèÿ ïðèâåäåíû â ðàçäåëå «Èíèöèàëèçàöèÿ ãëîáàëüíûõ îáúåêòîâ» ýòîé ãëàâû.
Êîíñòàíòû â ïåðå÷èñëåíèÿõ
Ïåðå÷èñëåíèÿ (åïèò) íå î÷åíü øèðîêî èñïîëüçîâàëèñü â ÿçûêå Ñ ïî îäíîé ïðîñòîé ïðè÷èíå:
ñèìâîëè÷åñêèå èìåíà êîíñòàíò èìåþò ãëîáàëüíóþ îáëàñòü äåéñòâèÿ è áûñòðî çàõëàìëÿþò
ïðîñòðàíñòâî èìåí.  C++ ýòà ïðîáëåìà èñ÷åçëà, ïîñêîëüêó îáëàñòü äåéñòâèÿ ñèìâîëè÷åñêèõ èìåí
îãðàíè÷èâàåòñÿ êëàññîì èëè ñòðóêòóðîé.
class Foo {
public:
enum Status { kOpen = 1, kClosed };
};
// Ãäå-òî â ïðîãðàììå
Foo::Status s = Foo::kOpen;
Îáðàòèòå âíèìàíèå — îáëàñòü äåéñòâèÿ äîëæíà áûòü ÿâíî óêàçàíà êàê â èìåíè òèïà, òàê è â
ñèìâîëè÷åñêîì èìåíè. Ñëåäîâàòåëüíî, ñèìâîëè÷åñêèå èìåíà kOpen è kClosed ìîæíî èñïîëüçîâàòü â
ïðîãðàììå è äëÿ äðóãèõ öåëåé. Êîìïèëÿòîð ðàññìàòðèâàåò ñèìâîëè÷åñêèå èìåíà ïåðå÷èñëåíèé êàê
ìàêðîñû, à íå êàê êîíñòàíòíûå ïåðåìåííûå. Ýòî îáñòîÿòåëüñòâî ìîæåò îêàçàòüñÿ âàæíûì ïðè
èíèöèàëèçàöèè ãëîáàëüíûõ ïåðåìåííûõ (ñì, äàëåå â ýòîé ãëàâå).
Óêàçàòåëü íà êîíñòàíòó
Ñ óêàçàòåëÿìè äåëî îáñòîèò íåñêîëüêî ñëîæíåå, ïîñêîëüêó ïðèõîäèòñÿ ó÷èòûâàòü äâà çíà÷åíèÿ: àäðåñ
è ñîäåðæèìîå ïàìÿòè ïî ýòîìó àäðåñó. Â ñëåäóþùåì ïðèìåðå ð — ýòî óêàçàòåëü íà êîíñòàíòó;
íàõîäÿùèéñÿ â óêàçàòåëå àäðåñ ìîæåò èçìåíèòüñÿ, íî ñîäåðæèìîå ïàìÿòè ïî ýòîìó àäðåñó — íåò.
const int* p;
int i = 17;
p = &i; // Ìîæíî
*p = 29; // Íåëüçÿ
Ñêàçàííîå òàêæå îòíîñèòñÿ ê ñòðóêòóðàì è îáúåêòàì.
class foo {
public:
int x;
};
const foo* f = new foo;
f->x = 17; // Íåëüçÿ, ïðèñâîåíèå ÷ëåíàì êëàññà íå äîïóñêàåòñÿ

21
Êîíñòàíòíûé óêàçàòåëü
Ñ êîíñòàíòíûìè óêàçàòåëÿìè âñå íàîáîðîò: àäðåñ èçìåíÿòü íåëüçÿ, íî çàòî ìîæíî èçìåíÿòü
ñîäåðæèìîå ïàìÿòè ïî ýòîìó àäðåñó.
int i = 17;
int j = 29;
int* const p; // Íåëüçÿ! Äîëæíî áûòü çàäàíî íà÷àëüíîå çíà÷åíèå
int* const p1 = &i; // Ïîðÿäîê
*p1 = 29; // Ìîæíî; âåëè÷èíà, íà êîòîðóþ ññûëàåòñÿ óêàçàòåëü,
// ìîæåò èçìåíÿòüñÿ
p1 = &j; // Íåëüçÿ
Êîíñòàíòíûé óêàçàòåëü íà êîíñòàíòó
Êîíñòàíòíûé óêàçàòåëü íà êîíñòàíòó (ïîïðîáóéòå-êà òðèæäû áûñòðî ïðîèçíåñòè ýòî âñëóõ!) èçìåíèòü
âîîáùå íåëüçÿ. Ýòî íåèçìåíÿåìûé àäðåñ íåèçìåíÿåìîé âåëè÷èíû.
int i = 17;
int j = 29;
const int* const p; // Íåëüçÿ. Äîëæåí áûòü çàäàí íà÷àëüíûé àäðåñ
const int* const p1 = &i; // Ìîæíî
*p1 = 29; // Íåëüçÿ
p1 = &j; // Íåëüçÿ
Êîíñòàíòíûå àðãóìåíòû ôóíêöèé
Êîíñòàíòíûé àðãóìåíò ôóíêöèè äîëæåí ïîä÷èíÿòüñÿ òåì æå ïðàâèëàì, ÷òî è ëþáàÿ äðóãàÿ
êîíñòàíòíàÿ ïåðåìåííàÿ.
void f(const int* p)
{
*p = 17; // Íåëüçÿ
int i = 29;
p = &i; // Ìîæíî, íî çà÷åì?
}
// Ãäå-òî â ïðîãðàììå
int i = 17;
f(&i); // Ïîðÿäîê, ôàêòè÷åñêèé àðãóìåíò íå îáÿçàí áûòü êîíñòàíòîé
Îáðàòèòå âíèìàíèå — àðãóìåíò, óêàçàííûé ïðè âûçîâå ôóíêöèè, íå îáÿçàí áûòü êîíñòàíòíûì. Ýòîò
âîïðîñ öåëèêîì îñòàåòñÿ íà óñìîòðåíèå ñòîðîíû-ïîëó÷àòåëÿ. Ïåðåäà÷à ïî ññûëêå îñóùåñòâëÿåòñÿ ïî
òåì æå ïðàâèëàì, ÷òî è ïåðåäà÷à ïî àäðåñó.
void f(const int& p)
{
p = 17; // Íåëüçÿ
int i = 29;
p = i; // Ìîæíî (íà ãðàíè ôîëà)
}
// Ãäå-òî ãëóáîêî â ïðîãðàììå
int i = 17;
f(i); // Ïîðÿäîê

22
Íåêîíñòàíòíûå àðãóìåíòû ôóíêöèé
Åñëè ôîðìàëüíûé àðãóìåíò ôóíêöèè îáúÿâëåí íåêîíñòàíòíûì, òî è ôàêòè÷åñêèé àðãóìåíò,
èñïîëüçóåìûé ïðè âûçîâå, òîæå äîëæåí áûòü íåêîíñòàíòíûì.
void f(int*);
int i = 17;
const int* p = &i;
const int j = 29;
f(&i); // Ìîæíî, ïîòîìó ÷òî i – íå êîíñòàíòà
f(p); // Íåëüçÿ
f(&j); // Òîæå íåëüçÿ, ïîòîìó ÷òî j - êîíñòàíòà
Ýòî åùå îäíî ñðåäñòâî, ñ ïîìîùüþ êîòîðîãî êîìïèëÿòîð ñîáëþäàåò ïðèíöèï «åäèíîæäû êîíñòàíòíûé
âñåãäà îñòàåòñÿ êîíñòàíòíûì». Äàæå åñëè ôóíêöèÿ f íà ñàìîì äåëå íå èçìåíÿåò çíà÷åíèÿ ñâîåãî
ôîðìàëüíîãî ïàðàìåòðà, ýòî íè íà ÷òî íå âëèÿåò.
Êîíñòàíòíûå ôóíêöèè êëàññîâ
 êîíñòàíòíûõ ôóíêöèÿõ êëàññîâ ïåðåìåííàÿ this èíòåðïðåòèðóåòñÿ êàê óêàçàòåëü íà êîíñòàíòó.
Êîìïèëÿòîð äàñò âàì ïî ðóêàì, åñëè âû ïîïðîáóåòå âîñïîëüçîâàòüñÿ ïåðåìåííîé this äëÿ èçìåíåíèÿ
ïåðåìåííîé êëàññà èëè íàéòè äëÿ íåå èíîå, íåêîíñòàíòíîå ïðèìåíåíèå. Ñìûñë êëþ÷åâîãî ñëîâà const
çàâèñèò îò åãî ìåñòà â îáúÿâëåíèè ôóíêöèè; äëÿ êîíñòàíòíûõ ôóíêöèé îíî, ñëîâíî áîðîäàâêà, òîð÷èò
ïîñëå ñèãíàòóðû ôóíêöèè.
class foo {
private:
int x;
public:
void f() const;
void g();
};
void h(int*);
void m(foo*);
void foo::f();
{
x = 17; // Íåëüçÿ: èçìåíÿåòñÿ ïåðåìåííàÿ êëàññà
this->g(); // Íåëüçÿ: g – íåêîòîðàÿ ôóíêöèÿ
h(&x); // Íåëüçÿ: h ìîæåò èçìåíèòü x
m(this); // Íåëüçÿ: íåêîíñòàíòíûé àðãóìåíò â m()
}
Ïåðâàÿ îøèáêà — ïîïûòêà èçìåíèòü ïåðåìåííóþ êëàññà ÷åðåç this.  êîíñòàíòíûõ ôóíêöèÿõ êëàññà
foo ïåðåìåííàÿ this ôàêòè÷åñêè îáúÿâëÿåòñÿ êàê const foo* this;. Âòîðàÿ îøèáêà ñëîæíåå. Èç
ïðèâåäåííîãî ôðàãìåíòà íåèçâåñòíî, èçìåíÿåò ëè ôóíêöèÿ g êàêèå-ëèáî ïåðåìåííûå êëàññà foo, íî ýòî
è íå âàæíî; îäíîé âîçìîæíîñòè äîñòàòî÷íî, ÷òîáû âàø êîìïèëÿòîð ðàçðàçèëñÿ íåãîäóþùèìè âîïëÿìè.
Èç êîíñòàíòíîé ôóíêöèè êëàññà íåëüçÿ âûçûâàòü íåêîíñòàíòíûå ôóíêöèè ÷åðåç this. Ïîõîæàÿ
ñèòóàöèÿ âîçíèêàåò ñ òðåòüåé è ÷åòâåðòîé îøèáêîé — êîìïèëÿòîð ïîïûòàåòñÿ ñïàñòè âàñ îò ñàìîãî
ñåáÿ è íå äîïóñòèò ïîòåíöèàëüíî îïàñíûå ñòðîêè.
Îäèí èç âåðíûõ ïðèçíàêîâ ïðîôåññèîíàëà C++ — êëþ÷åâûå ñëîâà const, îáèëüíî ðàçáðîñàííûå ïî
ôóíêöèÿì êëàññîâ. Ëþáàÿ ôóíêöèÿ êëàññà, êîòîðàÿ ãàðàíòèðîâàííî íå èçìåíÿåò this, äîëæíà áåç
ìàëåéøèõ ðàçìûøëåíèé îáúÿâëÿòüñÿ êîíñòàíòíîé. Âïðî÷åì, êàê âèäíî èç ïðèâåäåííîãî âûøå
ôðàãìåíòà, ýòà ñòðàòåãèÿ ðàáîòàåò ëèøü â òîì ñëó÷àå, åñëè âñå ó÷àñòíèêè êîìàíäû ñëåäóþò âàøåìó
ïðèìåðó è îáúÿâÿò êîíñòàíòíûìè ñâîè ôóíêöèè,  ïðîòèâíîì ñëó÷àå âîçíèêàþò êàñêàäíûå îøèáêè.
×àñòî âûÿñíÿåòñÿ, ÷òî íåäàâíî êóïëåííàÿ áèáëèîòåêà êëàññîâ íå èñïîëüçóåò êîíñòàíòíûå ôóíêöèè è

23
íàðóøàåò âàø ïóðèòàíñêèé ñòèëü êîäèðîâàíèÿ. Ìîðàëü: êîíñòàíòíûå ôóíêöèè êëàññîâ íóæíî
èñïîëüçîâàòü ëèáî ñ ïîëíûì ôàíàòèçìîì (æåëàòåëüíî), ëèáî íå èñïîëüçîâàòü âîâñå.
Ñòåêîâûå è äèíàìè÷åñêèå îáúåêòû
Èíîãäà ìíå êàæåòñÿ, ÷òî C++ ëó÷øå èçó÷àòü áåç ïðåäâàðèòåëüíîãî çíàêîìñòâà ñ C.  C++ ÷àñòî
èñïîëüçóþòñÿ òå æå òåðìèíû, ÷òî è â Ñ, íî çà íèìè êðîþòñÿ ñîâåðøåííî èíîé ñìûñë è ïðàâèëà
ïðèìåíåíèÿ. Íàïðèìåð, âîçüìåì ïðèìèòèâíûé öåëûé òèï.
int x = 17;
 C++ ýòî áóäåò ýêçåìïëÿð âñòðîåííîãî «êëàññà» int. Â Ñ ýòî áóäåò... ïðîñòî int. Âñòðîåííûå êëàññû
èìåþò ñâîè êîíñòðóêòîðû. Ó êëàññà int åñòü êîíñòðóêòîð ñ îäíèì àðãóìåíòîì, êîòîðûé
èíèöèàëèçèðóåò îáúåêò ïåðåäàâàåìûì çíà÷åíèåì. Òåîðåòè÷åñêè ñóùåñòâóåò è äåñòðóêòîð, õîòÿ îí
íè÷åãî íå äåëàåò è ëèêâèäèðóåòñÿ âñåìè íîðìàëüíûìè ðàçðàáîò÷èêàìè êîìïèëÿòîðîâ â ïðîöåññå
îïòèìèçàöèè. Âàæíî îñîçíàòü, ÷òî âñòðîåííûå òèïû çà î÷åíü ðåäêèìè èñêëþ÷åíèÿìè ïîä÷èíÿþòñÿ òåì
æå áàçîâûì ïðàâèëàì, ÷òî è âàøè ðàñøèðåííûå òèïû.
Âû äîëæíû ïîíèìàòü ýòó òåîðåòè÷åñêóþ îñîáåííîñòü C++, ÷òîáû ïðàâèëüíî îòíîñèòüñÿ ê ñòåêîâûì è
äèíàìè÷åñêèì îáúåêòàì è ñâÿçàííûì ñ íèìè ïåðåìåííûì.
Ðàçìåùåíèå â ñòåêå
×òîáû âûäåëèòü ïàìÿòü äëÿ ñòåêîâîé ïåðåìåííîé â îáëàñòè äåéñòâèÿ áëîêà, äîñòàòî÷íî ïðîñòî
îáúÿâèòü åå îáû÷íûì îáðàçîì.
{
int i;
foo f(constructor_args);
// Ïåðåä âûõîäîì èç áëîêà âûçûâàþòñÿ äåñòðóêòîðû i è f
}
Ñòåêîâûå îáúåêòû ñóùåñòâóþò ëèøü â ãðàíèöàõ ñîäåðæàùåãî èõ áëîêà. Ïðè âûõîäå çà åãî ïðåäåëû
àâòîìàòè÷åñêè âûçûâàåòñÿ äåñòðóêòîð. Ðàçóìååòñÿ, ïîëó÷åíèå àäðåñà ñòåêîâîãî îáúåêòà — äåëî
ðèñêîâàííîå, åñëè òîëüêî âû àáñîëþòíî, ñòîïðîöåíòíî íå óâåðåíû, ÷òî ýòîò óêàçàòåëü íå áóäåò
èñïîëüçîâàí ïîñëå âûõîäà çà ïðåäåëû îáëàñòè äåéñòâèÿ îáúåêòà. Âñå ôðàãìåíòû íàïîäîáèå
ïðèâåäåííîãî íèæå âñåãäà ñ÷èòàþòñÿ ïîòåíöèàëüíî îïàñíûìè:
{
int i;
foo f;
SomeFunction(&f);
}
Áåç èçó÷åíèÿ ôóíêöèè SomeFunction íåâîçìîæíî ñêàçàòü, áåçîïàñåí ëè ýòîò ôðàãìåíò.
SomeFunction ìîæåò ïåðåäàòü àäðåñ äàëüøå èëè ñîõðàíèòü åãî â êàêîé-íèáóäü ïåðåìåííîé, à ïî
çàêîíó Ìýðôè ýòîò àäðåñ íàâåðíÿêà áóäåò èñïîëüçîâàí óæå ïîñëå óíè÷òîæåíèÿ îáúåêòà f. Äàæå åñëè
ñâåðõòùàòåëüíûé àíàëèç SomeFunction ïîêàæåò, ÷òî àäðåñ íå ñîõðàíÿåòñÿ ïîñëå âûçîâà, ÷åðåç ïàðó
ëåò êàêîé-íèáóäü íîâûé ïðîãðàììèñò ìîäèôèöèðóåò SomeFunction, ïðîäëèò ñóùåñòâîâàíèå àäðåñà
íà ïàðó ìàøèííûõ êîìàíä è — ÁÓÌ!!! Ëó÷øå ïîëíîñòüþ èñêëþ÷èòü òàêóþ âîçìîæíîñòü è íå
ïåðåäàâàòü àäðåñà ñòåêîâûõ îáúåêòîâ.
Äèíàìè÷åñêîå ðàçìåùåíèå
×òîáû âûäåëèòü ïàìÿòü äëÿ îáúåêòà â êó÷å (heap), âîñïîëüçóéòåñü îïåðàòîðîì new new.
foo* f = new foo(constructor_args);
Âðîäå áû âñå ïðîñòî. Îïåðàòîð new âûäåëÿåò ïàìÿòü è âûçûâàåò ñîîòâåòñòâóþùèé êîíñòðóêòîð íà
îñíîâàíèè ïåðåäàííûõ àðãóìåíòîâ. Íî êîãäà ýòîò îáúåêò óíè÷òîæàåòñÿ? Ïîäðîáíûé îòâåò íà ýòîò
âîïðîñ çàéìåò ïðèìåðíî òðåòü êíèãè, íî ÿ íå áóäó âäàâàòüñÿ â òåõíè÷åñêèå äåòàëè è îòâå÷ó òàê: «Êîãäà

24
êòî-íèáóäü âûçîâåò îïåðàòîð delete äëÿ åãî àäðåñà». Ñàì ïî ñåáå îáúåêò èç ïàìÿòè íå óäàëèòñÿ; âû
äîëæíû ÿâíî ñîîáùèòü ñâîåé ïðîãðàììå, êîãäà åãî ñëåäóåò óíè÷òîæèòü.
Óêàçàòåëè è ññûëêè
Ïîïûòêè ñâÿçàòü óêàçàòåëè ñ äèíàìè÷åñêèìè îáúåêòàìè ÷àñòî ïðèâîäÿò ê íåäîðàçóìåíèÿì. Â
ñóùíîñòè, îíè íå èìåþò äðóã ñ äðóãîì íè÷åãî îáùåãî. Âû ìîæåòå ïîëó÷èòü àäðåñ ñòåêîâîãî îáúåêòà è
âûïîëíèòü îáðàòíîå ïðåîáðàçîâàíèå, òî åñòü ðàçûìåíîâàíèå (dereferencing) àäðåñà äèíàìè÷åñêîãî
îáúåêòà. È íà òî, è íà äðóãîå ìîæíî ñîçäàòü ññûëêó.
{
foo f;
foo* p = &f;
f.MemberFn(); // Èñïîëüçóåò ñàì îáúåêò
p->MemberFn(); // Èñïîëüçóåò åãî àäðåñ
p = new foo;
foo& r = *p; // Ññûëêà íà îáúåêò
r.MemberFn(); // Òî æå, ÷òî è p->MemberFn()
}
Êàê âèäèòå, âûáîð îïåðàòîðà . èëè -> çàâèñèò îò òèïà ïåðåìåííîé è íå èìååò îòíîøåíèÿ ê àòðèáóòàì
ñàìîãî îáúåêòà. Ðàç óæ ìû çàãîâîðèëè îá ýòîì, ïðàâèëüíûå íàçâàíèÿ ýòèõ îïåðàòîðîâ (. è ->) —
ñåëåêòîðû ÷ëåíîâ êëàññà (member selectors). Åñëè âû íàçîâåòå èõ «òî÷êîé» èëè «ñòðåëêîé» íà ñåìèíàðå
ñ êîêòåéëÿìè, íàñòóïèò ãðîáîâàÿ òèøèíà, âñå ïîâåðíóòñÿ è ïðåçðèòåëüíî ïîñìîòðÿò íà âàñ, à â äàëüíåì
óãëó êòî-íèáóäü âûðîíèò ñâîé áîêàë.
Íåäîñòàòêè ñòåêîâûõ îáúåêòîâ
Åñëè èñïîëüçîâàòü îïåðàòîð delete äëÿ ñòåêîâîãî îáúåêòà, òî ïðè áîëüøîì âåçåíèè âàøà ïðîãðàììà
ïðîñòî ãðîõíåòñÿ. À åñëè âàì (êàê è áîëüøèíñòâó èç íàñ) íå ïîâåçåò, òî ïðîãðàììà íà÷íåò âåñòè ñåáÿ,
êàê ðåâíèâàÿ ëþáîâíèöà — îíà áóäåò âûòâîðÿòü, âñÿêèå ãàäîñòè â ðàçíûõ ìåñòàõ ïàìÿòè, íî íå ñêàæåò,
íà ÷òî æå îíà ðàçîçëèëàñü. Äåëî â òîì, ÷òî â áîëüøèíñòâå ðåàëèçàöèé C++ îïåðàòîð new çàïèñûâàåò
ïàðó ñêðûòûõ áàéòîâ ïåðåä âîçâðàùàåìûì àäðåñîì. Â ýòèõ áàéòàõ óêàçûâàåòñÿ ðàçìåð âûäåëåííîãî
áëîêà. Ïî íèì îïåðàòîð delete îïðåäåëÿåò, ñêîëüêî ïàìÿòè çà óêàçàííûì àäðåñîì ñëåäóåò îñâîáîäèòü.
Ïðè âûäåëåíèè ïàìÿòè ïîä ñòåêîâûå îáúåêòû îïåðàòîð new íå âûçûâàåòñÿ, ïîýòîìó ýòè
äîïîëíèòåëüíûå äàííûå îòñóòñòâóþò. Åñëè âûçâàòü îïåðàòîð delete äëÿ ñòåêîâîãî îáúåêòà, îí
âîçüìåò ñîäåðæèìîå ñòåêà íàä âàøåé ïåðåìåííîé è èíòåðïðåòèðóåò åãî êàê ðàçìåð îñâîáîæäàåìîãî
áëîêà.
Èòàê, ìû çíàåì ïî êðàéíåé ìåðå äâå ïðè÷èíû, ïî êîòîðûì ñëåäóåò èçáåãàòü ñòåêîâûõ îáúåêòîâ — åñëè
ó âàñ íåò äåéñòâèòåëüíî âåñêèõ äîâîäîâ â èõ ïîëüçó:
1. Àäðåñ ñòåêîâîãî îáúåêòà ìîæåò áûòü ñîõðàíåí è èñïîëüçîâàí ïîñëå âûõîäà çà ãðàíèöû îáëàñòè
äåéñòâèÿ îáúåêòà.
2. Àäðåñ ñòåêîâîãî îáúåêòà ìîæåò áûòü ïåðåäàí îïåðàòîðó delete.
Ñëåäîâàòåëüíî, äëÿ ñòåêîâûõ îáúåêòîâ äåéñòâóåò õîðîøåå ïðàâèëî: Íèêîãäà íå ïîëó÷àéòå èõ àäðåñà
èëè àäðåñà èõ ÷ëåíîâ.
Äîñòîèíñòâà ñòåêîâûõ îáúåêòîâ
Ñ äðóãîé ñòîðîíû, ïàìÿòü â ñòåêå âûäåëÿåòñÿ ñ ãîëîâîêðóæèòåëüíîé áûñòðîòîé — òàê æå áûñòðî, êàê
êîìïèëÿòîð âûäåëÿåò ïàìÿòü ïîä äðóãèå àâòîìàòè÷åñêèå ïåðåìåííûå (ñêàæåì, öåëûå). Îïåðàòîð new
(ïî êðàéíåé ìåðå, åãî ñòàíäàðòíàÿ âåðñèÿ) òðàòèò íåñêîëüêî òàêòîâ íà òî, ÷òîáû ðåøèòü, îòêóäà âçÿòü
áëîê ïàìÿòè è ãäå îñòàâèòü äàííûå äëÿ åãî ïîñëåäóþùåãî îñâîáîæäåíèÿ. Áûñòðîäåéñòâèå — îäíà èç
âåñêèõ ïðè÷èí â ïîëüçó âûäåëåíèÿ ïàìÿòè èç ñòåêà. Êàê âû âñêîðå óáåäèòåñü, ñóùåñòâóåò íåìàëî
ñïîñîáîâ óñêîðèòü ðàáîòó îïåðàòîðà new, òàê ÷òî ýòà ïðè÷èíà ìåíåå âàæíà, ÷åì ìîæåò ïîêàçàòüñÿ ñ
ïåðâîãî âçãëÿäà.

25
Àâòîìàòè÷åñêîå óäàëåíèå — âòîðîå áîëüøîå ïðåèìóùåñòâî ñòåêîâûõ îáúåêòîâ, ïîýòîìó
ïðîãðàììèñòû ÷àñòî ñîçäàþò ìàëåíüêèå âñïîìîãàòåëüíûå ñòåêîâûå êëàññû, êîòîðûå èãðàþò ðîëü
«îáåðòêè» äëÿ äèíàìè÷åñêèõ îáúåêòîâ.  ñëåäóþùåì çàáàâíîì ïðèìåðå äèíàìè÷åñêèé êëàññ Foo
«óïàêîâûâàåòñÿ» â ñòåêîâûé êëàññ PFoo. Êîíñòðóêòîð âûäåëÿåò ïàìÿòü äëÿ Foo; äåñòðóêòîð
îñâîáîæäàåò åå. Åñëè âû íåçíàêîìû ñ îïåðàòîðàìè ïðåîáðàçîâàíèÿ, îáðàòèòåñü ê ñîîòâåòñòâóþùåìó
ðàçäåëó ýòîé ãëàâû. Â äâóõ ñëîâàõ, ôóíêöèÿ operator Foo*() ïîçâîëÿåò èñïîëüçîâàòü êëàññ PFoo âåçäå,
ãäå äîëæåí èñïîëüçîâàòüñÿ Foo* — íàïðèìåð, ïðè âûçîâå ôóíêöèè g().
class PFoo {
private:
Foo* f;
public:
PFoo() : f(new Foo) {}
~PFoo() { delete f; }
operator Foo*() { return f; }
}
void g(Foo*);
{
PFoo p;
g(p); // Âûçûâàåò ôóíêöèþ operator Foo*() äëÿ ïðåîáðàçîâàíèÿ
// Óíè÷òîæàåòñÿ p, à çà íèì – Foo
}
Îáðàòèòå âíèìàíèå, ÷òî ýòîò êëàññ íå ñîâñåì áåçîïàñåí, ïîñêîëüêó àäðåñ, âîçâðàùàåìûé ôóíêöèåé
operator Foo*(), ñòàíîâèòñÿ íåäåéñòâèòåëüíûì ïîñëå óäàëåíèÿ âìåùàþùåãî PFoo. Ìû ðàçáåðåìñÿ
ñ ýòèì ÷óòü ïîçæå.
Ìû åùå íå ðàç âñòðåòèìñÿ ñ ïîäîáíûìè ôîêóñàìè. Âñÿ ñîëü çàêëþ÷àåòñÿ â òîì, ÷òî ñòåêîâûå îáúåêòû
ìîãóò ïðèãîäèòüñÿ ïðîñòî èç-çà òîãî, ÷òî èõ íå ïðèõîäèòñÿ óäàëÿòü âðó÷íóþ. Âñêîðå ÿ ïîêàæó âàì, êàê
îðãàíèçîâàòü àâòîìàòè÷åñêîå óäàëåíèå äèíàìè÷åñêèõ îáúåêòîâ, íî ýòà ìåòîäèêà î÷åíü ñëîæíà è âðÿä
ëè ïðèãîäíà äëÿ ïîâñåäíåâíîãî ïðèìåíåíèÿ.
Ó ñòåêîâûõ îáúåêòîâ åñòü åùå îäíî ïðåèìóùåñòâî — åñëè âàø êîìïèëÿòîð ïîääåðæèâàåò ANSI-
ñîâìåñòèìóþ îáðàáîòêó èñêëþ÷åíèé (exception). Êîãäà âî âðåìÿ ðàñêðóòêè ñòåêà ïðîèñõîäèò
èñêëþ÷åíèå, äåñòðóêòîðû ñòåêîâûõ îáúåêòîâ âûçûâàþòñÿ àâòîìàòè÷åñêè. Äëÿ äèíàìè÷åñêèõ îáúåêòîâ
ýòîãî íå ñëó÷àåòñÿ, è âàøà êó÷à ìîæåò ïðåâðàòèòüñÿ â íàñòîÿùèé õàîñ. Ðèñêóÿ ïîâòîðèòüñÿ, ÿ ñêàæó,
÷òî ìû âåðíåìñÿ ê ýòîé òåìå ïîçäíåå.
Îáëàñòè äåéñòâèÿ è ôóíêöèè
Îäíî èç çíà÷èòåëüíûõ ïðåèìóùåñòâ C++ íàä Ñ — âîçìîæíîñòü îãðàíè÷åíèÿ îáëàñòè äåéñòâèÿ
ñèìâîëè÷åñêèõ èìåí. Âïðî÷åì, ýòî ïàëêà î äâóõ êîíöàõ, ïîñêîëüêó ïðàâèëà îïðåäåëåíèÿ îáëàñòè
äåéñòâèÿ èíîãäà äîâîëüíî çàïóòàííû. Êðîìå òîãî, â C++ ïîÿâèëàñü ïåðåãðóçêà ôóíêöèé è — êàê åå
ðàñøèðåíèå — ïåðåãðóçêà îïåðàòîðîâ. Ïðåäïîëàãàåòñÿ, ÷òî âû óæå çíàêîìû ñ àçàìè, ïîýòîìó â ñâîåì
êðàòêîì îáçîðå ÿ îãðàíè÷óñü ëèøü íåêîòîðûìè íåòðèâèàëüíûìè îñîáåííîñòÿìè ôóíêöèé è îáëàñòåé
äåéñòâèÿ.
Îáëàñòè äåéñòâèÿ
Îáëàñòü äåéñòâèÿ ñîçäàåòñÿ ñëåäóþùèìè êîíñòðóêöèÿìè:
• êëàññ;
• ñòðóêòóðà;
• îáúåäèíåíèå;
• áëîê;
• ãëîáàëüíîå ïðîñòðàíñòâî èìåí.

26
Ñèìâîëè÷åñêèå èìåíà, îáúÿâëåííûå â îáëàñòè äåéñòâèÿ, îòíîñÿòñÿ òîëüêî ê äàííîé îáëàñòè. Îíè íå
îãðàíè÷èâàþòñÿ ïåðå÷èñëåíèÿìè è ïðîñòûìè ïåðåìåííûìè. Ñòðóêòóðû, êëàññû è ôóíêöèè òàêæå
ìîãóò îïðåäåëÿòüñÿ â êîíêðåòíîé îáëàñòè äåéñòâèÿ.
Êëàññû
Êëàññ â C++ — íå÷òî áîëüøåå, ÷åì ïðîñòàÿ ñòðóêòóðà äàííûõ. Ýòî àíàëîã ìîäóëÿ èç äðóãèõ ÿçûêîâ
ïðîãðàììèðîâàíèÿ, ñðåäñòâî óïîðÿäî÷åíèÿ ñèìâîëüíûõ èìåí.
class Foo {
public:
static int y; // Ãëîáàëüíàÿ ïåðåìåííàÿ
static void GFn(); // Ãëîáàëüíàÿ ôóíêöèÿ
int x; // Ïåðåìåííàÿ êëàññà
Foo(); // Êîíñòðóêòîð
void Fn(); // Ôóíêöèÿ êëàññà
typedef int (*IntFn)(); // Òèï
enum Status { kOpen = 0, kClosed }; // Äðóãîé òèï
struct Bar { // Âëîæåííàÿ ñòðóêòóðà
int a;
int b;
static void BarFn();
}
private:
void Hn();
};
 ýòîì ôðàãìåíòå ïðèâåäåíû íåêîòîðûå âàðèàöèè íà òåìó êëàññîâ. Ïåðåìåííàÿ ó — ãëîáàëüíàÿ
ïåðåìåííàÿ, a GFn() — ãëîáàëüíàÿ ôóíêöèÿ, õîòÿ îáëàñòü äåéñòâèÿ èõ èìåí îãðàíè÷èâàåòñÿ êëàññîì
Foo. Âî âñåõ ôóíêöèÿõ êëàññà Foo ê íèì ìîæíî îáðàùàòüñÿ ïðîñòî ïî èìåíè, íî çà åãî ïðåäåëàìè
íåîáõîäèìî èñïîëüçîâàòü îïåðàòîð îáëàñòè äåéñòâèÿ :::
Foo::Foo()
{
GFn(); // Ìû óæå íàõîäèìñÿ â îáëàñòè äåéñòâèÿ Foo
}
void f()
{
Foo::GFn(); // Íåîáõîäèìî çàäàòü îáëàñòü äåéñòâèÿ
}
Àíàëîãè÷íî, îïðåäåëåíèå òèïà IntFn, ïåðå÷èñëåíèå Status è äàæå âëîæåííóþ ñòðóêòóðó Bar òàêæå
ìîæíî èñïîëüçîâàòü áåç óêàçàíèÿ îáëàñòè äåéñòâèÿ â ôóíêöèÿõ êëàññà Foo, íî â ëþáîì äðóãîì ìåñòå
ýòó îáëàñòü íåîáõîäèìî çàäàòü. Äëÿ âëîæåííûõ òèïîâ ñ îòêðûòîé âèäèìîñòüþ ñèíòàêñèñ óêàçàíèÿ
îáëàñòè äåéñòâèÿ ìîæåò ïðèíÿòü íåñêîëüêî óñòðàøàþùèé âèä, êàê âèäíî èç ñëåäóþùåãî ïðèìåðà äëÿ
ñòðóêòóðû Âàr:
Foo::Bar b;
Foo::Bar::BarFn();
Ïî ýòîé ïðè÷èíå âëîæåííûå ñòðóêòóðû ëèáî äåëàþòñÿ òðèâèàëüíûìè, ëèáî äîñòóï ê íèì
îãðàíè÷èâàåòñÿ.
×ëåíû êëàññà õ, Foo è Fn(), èìåþò ñìûñë ëèøü â êîíòåêñòå êîíêðåòíîãî ýêçåìïëÿðà (instance) ýòîãî
êëàññà. Äëÿ îáðàùåíèÿ ê íèì èñïîëüçóþòñÿ îïåðàòîðû-ñåëåêòîðû ÷ëåíîâ êëàññà, . è ->. Øèðîêèå
ìàññû (è, êàê ÿ âûÿñíèë íà ñîáñòâåííîì ãîðüêîì îïûòå, äàæå ðàçðàáîò÷èêè êîìïèëÿòîðîâ C++) ïî÷òè
íå çíàþò î òîì, ÷òî ñ ïîìîùüþ ñåëåêòîðîâ ìîæíî âûçûâàòü ñòàòè÷åñêèå ôóíêöèè êëàññà è îáðàùàòüñÿ

27
ê ñòàòè÷åñêèì ïåðåìåííûì êëàññà. Ñëåäóþùèé ôðàãìåíò âåðåí, õîòÿ áåäíûå ÷èòàòåëè âàøåé
ïðîãðàììû ïðèäóò â òàêîå çàìåøàòåëüñòâî, ÷òî ïîäîáíîå ìîæíî ïðîäåëûâàòü òîëüêî â ïîñëåäíèé äåíü
ïåðåä óâîëüíåíèåì:
Foo f;
f.Gfn(); // Òî æå, ÷òî è Foo::GFn();
Ñòðóêòóðû
Ñòðóêòóðà â C++ — ïî÷òè ÷òî ïîëíîöåííûé êëàññ. Ñî ñòðóêòóðîé ìîæíî äåëàòü âñå, ÷òî ìîæíî äåëàòü
ñ êëàññîì. Íàïðèìåð, ñòðóêòóðû ìîãóò ó÷àñòâîâàòü â íàñëåäîâàíèè; â íèõ ìîæíî îáúÿâëÿòü ñåêöèè
public, private, protected è äàæå âèðòóàëüíûå ôóíêöèè. Òåì íå ìåíåå, äëÿ ñòðóêòóð äåéñòâóþò
íåñêîëüêî èíûå ïðàâèëà: ïî óìîë÷àíèþ âñå ÷ëåíû ñ÷èòàþòñÿ îòêðûòûìè (public), ÷òîáû ãîòîâûå
ïðîãðàììû íà Ñ íå ïðèõîäèëîñü ïåðåïèñûâàòü çàíîâî ïîä êàíîíû C++.
Òåîðèÿ — âåùü õîðîøàÿ, íî äàâàéòå âåðíåìñÿ íà çåìëþ. Ñòîèò ëè äåìîíñòðèðîâàòü ñâîþ «êðóòèçíó» è
îáúÿâëÿòü ñòðóêòóðó ñ ìíîæåñòâåííûì íàñëåäîâàíèåì è âèðòóàëüíûìè ôóíêöèÿìè? Íà ïðàêòèêå
ñòðóêòóðû èñïîëüçóþòñÿ âìåñòî êëàññîâ ëèøü ïðè ñîáëþäåíèè ñëåäóþùèõ óñëîâèé:
• Ñòðóêòóðà íå ñîäåðæèò âèðòóàëüíûõ ôóíêöèé.
• Ñòðóêòóðà íå ÿâëÿåòñÿ ïðîèçâîäíîé îò ÷åãî-ëèáî, êðîìå ðàçâå ÷òî äðóãîé ñòðóêòóðû.
• Ñòðóêòóðà íå ÿâëÿåòñÿ áàçîâîé äëÿ ÷åãî-ëèáî, êðîìå ðàçâå ÷òî äðóãîé ñòðóêòóðû.
Íîðìàëüíûå ïðîãðàììèñòû C++ îáû÷íî èñïîëüçóþò ñòðóêòóðû ëèøü äëÿ ìàëåíüêèõ óäîáíûõ íàáîðîâ
äàííûõ ñ òðèâèàëüíûìè ôóíêöèÿìè.  ÷àñòíîñòè, ñòðóêòóðû ÷àñòî èñïîëüçóþòñÿ â ñèòóàöèÿõ, êîãäà
îáúåêò C++ äîëæåí áûòü ñîâìåñòèì íà áèòîâîì óðîâíå ñ âíåøíåé ñòðóêòóðîé äàííûõ (îñîáåííî ñî
ñòðóêòóðàìè Ñ). Ïðè ýòîì ìîæíî çàïðîñòî îáúÿâëÿòü êîíñòðóêòîðû è íåâèðòóàëüíûå ôóíêöèè (îñî-
áåííî òðèâèàëüíûå âñòðîåííûå), ïîñêîëüêó äëÿ íèõ íå ñîçäàåòñÿ v-òàáëèöà, êîòîðàÿ ìîãëà áû
íàðóøèòü áèòîâóþ ñîâìåñòèìîñòü.
Îáúåäèíåíèÿ
Îáúåäèíåíèÿ C++ ïî÷òè íå îòëè÷àþòñÿ îò îáúåäèíåíèé Ñ. Îíè ïîçâîëÿþò ñýêîíîìèòü íåñêîëüêî áàéò
çà ñ÷åò íàëîæåíèÿ ðàçëè÷íûõ ñòðóêòóð äàííûõ ïîâåðõ äðóã äðóãà. Îáúåäèíåíèÿ ìîãóò ñîäåðæàòü
íåâèðòóàëüíûå ôóíêöèè, â òîì ÷èñëå êîíñòðóêòîðû è äåñòðóêòîðû, íî ïðè ýòîì îíè äîëæíû
ïîä÷èíÿòüñÿ äîâîëüíî æåñòêèì îãðàíè÷åíèÿì:
• ×ëåíû îáúåäèíåíèÿ íå ìîãóò èìåòü êîíñòðóêòîðîâ (õîòÿ ñàìî îáúåäèíåíèå — ìîæåò).
• Îáúåäèíåíèå íå ìîæåò áûòü ïðîèçâîäíûì îò ÷åãî-ëèáî.
• Íè÷òî íå ìîæåò áûòü ïðîèçâîäíûì îò îáúåäèíåíèÿ.
• Äåñòðóêòîðû ÷ëåíîâ íå âûçûâàþòñÿ, õîòÿ äåñòðóêòîð ñàìîãî îáúåäèíåíèÿ, åñëè îí åñòü,
âûçûâàåòñÿ.
Ïîñêîëüêó îáúåäèíåíèÿ íå ó÷àñòâóþò â èåðàðõèè íàñëåäîâàíèÿ, íåò ñìûñëà îáúÿâëÿòü â íèõ
âèðòóàëüíûå ôóíêöèè èëè çàùèùåííûå ÷ëåíû. ×ëåíû îáúåäèíåíèé ðàçðåøàåòñÿ îáúÿâëÿòü çàêðûòûìè
(private) èëè îòêðûòûìè (public). Îáúåäèíåíèÿ ïðèãîäÿòñÿ ëèøü òîãäà, êîãäà âàì äåéñòâèòåëüíî
íóæíî ñýêîíîìèòü ïàìÿòü, êîãäà âû íå ñîáèðàåòåñü äåëàòü îáúåäèíåíèå ïðîèçâîäíûì èëè áàçîâûì, à
òàêæå âêëþ÷àòü â íåãî âèðòóàëüíûå ôóíêöèè èëè êîíñòðóêòîðû. Èíà÷å ãîâîðÿ, ïîëüçû îò íèõ íå òàê
óæ ìíîãî.
Áëîêè
Âñå, ÷òî ñòîèëî áû ñêàçàòü î áëîêàõ, óæå èçâåñòíî âàì èç Ñ èëè èç ïðåäûäóùåãî îïèñàíèÿ ñòåêîâûõ
îáúåêòîâ.
Ãëîáàëüíûå ïðîñòðàíñòâà èìåí
Ãëîáàëüíûå ïðîñòðàíñòâà èìåí C++ íàñòîëüêî ñëîæíû, ÷òî â ìîåì ïðåäñòàâëåíèè ïðîöåññ êîìïèëÿöèè
ãëîáàëüíûõ êîíñòðóêöèé íàïîìèíàåò ìàãè÷åñêèé ðèòóàë ñ äûìîì áëàãîâîíèé è ïåíèåì ìàíòð. ß
ïîñòàðàþñü èçëîæèòü ýòè ïðàâèëà êàê ìîæíî ïðîùå. Îáëàñòü äåéñòâèÿ ãëîáàëüíûõ òèïîâ

28
îãðàíè÷èâàåòñÿ ôàéëîì, â êîòîðîì îíè îáúÿâëÿþòñÿ. Ãëîáàëüíûå ïåðåìåííûå è ôóíêöèè ê òîìó æå
ïîä÷èíÿþòñÿ ïðàâèëàì êîìïîíîâêè äëÿ íåñêîëüêèõ èñõîäíûõ ôàéëîâ. Ðàññìîòðèì ñëåäóþùóþ
ñèòóàöèþ:
// Â ôàéëå Foo.cpp
typedef int Symbol;
// Â ôàéëå Bar.cpp
typedef void (*Symbol)();
Íèêàêîãî êîíôëèêòà íå âîçíèêíåò, åñëè òîëüêî ïî ìàçîõèñòñêèì ñîîáðàæåíèÿì âû íå âêëþ÷èòå îäèí
ôàéë ñ ðàñøèðåíèåì .ñðð â äðóãîé äèðåêòèâîé #include. Ñèìâîëè÷åñêîå èìÿ Symbol èçâåñòíî
êîìïèëÿòîðó ëèøü â òåõ èñõîäíûõ ôàéëàõ, â êîòîðûõ îíî âñòðå÷àåòñÿ, ïîýòîìó â ðàçíûõ èñõîäíûõ
ôàéëàõ åãî ìîæíî èñïîëüçîâàòü ïî-ðàçíîìó. Ñëåäóþùèé ôðàãìåíò íåâåðåí, ïîñêîëüêó íà ýòîò ðàç
ñèìâîëè÷åñêîå èìÿ ñîîòâåòñòâóåò ïåðåìåííîé, à íå òèïó. Èìÿ ïåðåìåííîé äîëæíî áûòü óíèêàëüíûì
äëÿ âñåõ ôàéëîâ, ïåðåäàâàåìûõ êîìïîíîâùèêó.
// Â ôàéëå Foo.cpp
int Symbol;
// Â ôàéëå Bar.cpp
void (*Symbol)();
Åäèíñòâåííîå èñêëþ÷åíèå èç ýòîãî ïðàâèëà îòíîñèòñÿ ê ïåðåãðóçêå ôóíêöèé, î êîòîðîé áóäåò
ðàññêàçàíî â ñëåäóþùåì ðàçäåëå. Êîíå÷íî, êîíôëèêòû èìåí ÷àñòî âîçíèêàþò â ëþáîì äîñòàòî÷íî
áîëüøîì ïðîåêòå, â êîòîðîì íåñêîëüêî ïðîãðàììèñòîâ ðàáîòàþò íàä ðàçíûìè èñõîäíûìè ôàéëàìè.
Îäíî èç âîçìîæíûõ ðåøåíèé — èñïîëüçîâàíèå ñòàòè÷åñêèõ ÷ëåíîâ; äðóãîå — îáúÿâëåíèå ãëîáàëüíûõ
ïåðåìåííûõ è ôóíêöèé ñòàòè÷åñêèìè. Åñëè ïåðåìåííàÿ èëè ôóíêöèÿ îáúÿâëÿåòñÿ ñòàòè÷åñêîé, îíà
îïðåäåëåíà ëèøü â ãðàíèöàõ èñõîäíîãî ôàéëà.
// Â ôàéëå Foo.cpp
static int Symbol;
// Â ôàéëå Bar.cpp
static void (*Symbol)();
Óâèäåâ êëþ÷åâîå ñëîâî static, êîìïèëÿòîð ïðîñëåäèò çà òåì, ÷òîáû êîìïîíîâùèê íå ïåðåïóòàë äâå
ðàçíûå âåðñèè îäíîãî ñèìâîëè÷åñêîãî èìåíè ïðè óñëîâèè ÷òî èñõîäíûå ôàéëû íå êîìïèëèðóþòñÿ
âìåñòå; áóäóò ñãåíåðèðîâàíû äâå ðàçíûå ïåðåìåííûå.
Ê ëþáîìó ñèìâîëè÷åñêîìó èìåíè, îáúÿâëåííîìó â ãëîáàëüíîì ïðîñòðàíñòâå èìåí, ìîæíî îáðàòèòüñÿ ñ
ïîìîùüþ îïåðàòîðà :: áåç óêàçàíèÿ îáëàñòè äåéñòâèÿ:
::Fn(); // Âûçâàòü ãëîáàëüíóþ ôóíêöèþ ñ çàäàííûì èìåíåì
int x = ::i; // Ïðèñâîèòü x çíà÷åíèå ãëîáàëüíîé ïåðåìåííîé
::SomeType y; // Èñïîëüçîâàòü ãëîáàëüíî îáúÿâëåííûé òèï
ßâíî çàäàííàÿ îáëàñòü äåéñòâèÿ âñåãäà îòìåíÿåò âñå ñèìâîëè÷åñêèå èìåíà, îïðåäåëåííûå ëîêàëüíî —
íàïðèìåð, âíóòðè áëîêà èëè êëàññà.
Ïåðåãðóçêà
 C++ ñóùåñòâóåò íåñêîëüêî ñïîñîáîâ ìíîãîêðàòíîãî èñïîëüçîâàíèÿ èìåí ôóíêöèé.  ÷àñòíîñòè,
ïðîñòðàíñòâà èìåí ôóíêöèé ôîðìèðóþòñÿ íà îñíîâå êëàññîâ. Îäíîèìåííûå ôóíêöèè â êëàññàõ, íå
ñâÿçàííûõ äðóã ñ äðóãîì, âûïîëíÿþò ñîâåðøåííî ðàçíûå çàäà÷è. Ïåðåãðóçêà ôóíêöèé ðàçâèâàåò
âåëèêóþ òðàäèöèþ ðàçäåëåíèÿ ïðîñòðàíñòâ èìåí ôóíêöèé è ïîçâîëÿåò ìíîãîêðàòíî èñïîëüçîâàòü
èìåíà ôóíêöèé â ãðàíèöàõ îäíîé îáëàñòè äåéñòâèÿ.
Àðãóìåíòû
Äâå ôóíêöèè ñ îäèíàêîâûìè èìåíàìè ñ÷èòàþòñÿ ðàçíûìè, åñëè îíè îòëè÷àþòñÿ ïî êîëè÷åñòâó,
ïîðÿäêó èëè òèïó àðãóìåíòîâ.
void Fn();

29
void Fn(int);
void Fn(long); // Ìîæíî, åñëè òèïû long è int îòëè÷àþòñÿ ðàçìåðîì
int Fn(int); // Íåëüçÿ – îòëè÷àåòñÿ òîëüêî òèï âîçâðàùàåìîãî çíà÷åíèÿ
int Fn(char*); // Ìîæíî, îòëè÷àþòñÿ àðãóìåíòû
void Fn(int, char*);
void Fn(char*, int); // Ìîæíî, àðãóìåíòû ñëåäóþò â äðóãîì ïîðÿäêå
void Fn(char* s, int x, int y = 17); // Ìîæíî – òðè àðãóìåíòà âìåñòî äâóõ
Fn(“hello”, 17); // Îøèáêà – ñîâïàäàþò äâå ñèãíàòóðû
Ïîêà àðãóìåíòû îòëè÷àþòñÿ, êîìïèëÿòîð íå æàëóåòñÿ íà èçìåíåíèå âîçâðàùàåìîãî òèïà.
Èíèöèàëèçàöèÿ ïî óìîë÷àíèþ (òàêàÿ êàê ó=17) ìîæåò ïðèñóòñòâîâàòü ïðè îáúÿâëåíèè ôóíêöèè, õîòÿ
ïîçäíåå îíà ìîæåò ñòàòü ïðè÷èíîé íåîäíîçíà÷íîñòè ïðè âûçîâå ôóíêöèè (êàê â ïîñëåäíåé ñòðîêå
ïðèìåðà).
Êîíñòàíòíûå ôóíêöèè
Êîíñòàíòíàÿ ôóíêöèÿ, àðãóìåíòû êîòîðîé ñîâïàäàþò ñ àðãóìåíòàìè íåêîíñòàíòíîé ôóíêöèè, òåì íå
ìåíåå ñ÷èòàåòñÿ äðóãîé ôóíêöèåé. Êîìïèëÿòîð âûçûâàåò êîíñòàíòíóþ èëè íåêîíñòàíòíóþ âåðñèþ â
çàâèñèìîñòè îò òèïà ïåðåìåííîé, óêàçûâàþùåé èëè ññûëàþùåéñÿ íà îáúåêò.
class Foo {
public:
void Fn();
void Fn() const; // Äðóãàÿ ôóíêöèÿ!
};
Foo* f = new Foo;
f->Fn(); // Âûçûâàåòñÿ íåêîíñòàíòíàÿ âåðñèÿ
const Foo* f1 = f;
f1->Fn(); // Âûçûâàåòñÿ êîíñòàíòíàÿ âåðñèÿ
Âèäèìîñòü
 C++ ñóùåñòâóåò ïîäðîáíàÿ (à ïî ìíåíèþ íåêîòîðûõ, äàæå ñëèøêîì ïîäðîáíàÿ) ñèñòåìà ïðàâèë, ïî
êîòîðûì ìîæíî óçíàòü, ÷òî âû âèäèòå ïðÿìî ïåðåä ñîáîé, à ÷òî âûøëî èç âàøåãî ïîëÿ çðåíèÿ. Áàçîâûå
ïðàâèëà äëÿ îòêðûòûõ çàùèùåííûõ è çàêðûòûõ ñèìâîëè÷åñêèõ èìåí â êëàññàõ è ñòðóêòóðàõ íàñòîëüêî
ïðîñòû, ÷òî ÿ íå ñòàíó èõ ïåðåñêàçûâàòü. Íèæå ïðèâåäåíà êðàòêàÿ ñâîäêà íàèáîëåå êàâåðçíûõ
âîïðîñîâ, îòíîñÿùèõñÿ ê ïîíÿòèþ âèäèìîñòè (visibility) â C++.
Çàêðûòîå íàñëåäîâàíèå
Ïðè çàêðûòîì íàñëåäîâàíèè îò áàçîâîãî êëàññà âñå åãî çàùèùåííûå è îòêðûòûå ÷ëåíû ñòàíîâÿòñÿ
çàêðûòûìè â ïðîèçâîäíîì êëàññå; ÷ëåíû çàêðûòîãî áàçîâîãî êëàññà íåäîñòóïíû äëÿ ïîëüçîâàòåëåé
ïðîèçâîäíîãî êëàññà. Äîñòóï ê íèì âîçìîæåí ëèøü èç ôóíêöèé áàçîâîãî è ïðîèçâîäíîãî êëàññà, à
òàêæå èç äðóçåé ïðîèçâîäíîãî êëàññà.
Êðîìå òîãî, ïðîèçâîäíûé êëàññ íåëüçÿ ïðåîáðàçîâàòü ê îäíîìó èç åãî çàêðûòûõ áàçîâûõ êëàññîâ èëè
íàäåÿòüñÿ, ÷òî ýòî ñäåëàåò êîìïèëÿòîð.
class Mixin {
private:
int x;
protected:
int y;
public:
Mixin();
Void a();
};

30
class Foo : private Mixin {...};
class Bar : public Foo {...};
Ïåðåìåííàÿ õ âèäíà ëèøü â ôóíêöèÿõ êëàññà Mixin — â êîíñòðóêòîðå è À(). Ïåðåìåííàÿ ó âèäíà
ëèøü â ôóíêöèÿõ êëàññà Foo, êàê è ôóíêöèÿ Mixin::A(). Âñå ÷ëåíû Mixin íå âèäíû â êëàññàõ,
ïðîèçâîäíûõ îò Foo (òàêèõ êàê Âàr â ýòîì ôðàãìåíòå). Âñå äðóçüÿ Foo âèäÿò õ è À(), à äðóçüÿ Bar —
íåò.
Ïåðåîáúÿâëåíèå ÷ëåíîâ
Õîòÿ îïèñàííàÿ ñèòóàöèÿ âîçíèêàåò äîâîëüíî ðåäêî, äîïóñêàåòñÿ ïåðåîáúÿâëåíèå âèðòóàëüíûõ
ôóíêöèé ñ öåëüþ èçìåíåíèÿ èõ àòðèáóòîâ âèäèìîñòè ïî îòíîøåíèþ ê áàçîâîìó êëàññó.
class Foo {
protected:
virtual void Fn();
};
class Bar : public Foo {
public:
virtual void Fn();
};
 êëàññå Foo ôóíêöèÿ Fn() áûëà çàùèùåííîé, íî â íîâîì âàðèàíòå îíà îáúÿâëåíà îòêðûòîé. Äëÿ
ïåðåìåííûõ êëàññà èëè íåâèðòóàëüíûõ ôóíêöèè ýòî ñäåëàòü íåëüçÿ. Ïåðåîáúÿâëåíèå ïåðåìåííîé èëè
íåâèðòóàëüíîé ôóíêöèè ñêðûâàåò ïðîòîòèï èç áàçîâîãî êëàññà.
class Foo {
private:
int x;
public:
void Fn();
};
class Bar : public Foo {
private:
int x; // Âòîðàÿ ïåðåìåííàÿ ñ òåì æå èìåíåì
public:
void Fn(); // Âòîðàÿ ôóíêöèÿ
};
// Â êëèåíòñêîé ïðîãðàììå
Bar *b = new Bar;
b->Fn(); // Âûçûâàåò Bar::Fn()
Foo* f = b; // Ìîæíî, ïîòîìó ÷òî Foo – îòêðûòûé áàçîâûé êëàññ
f->Fn(); // Âûçûâàåò Foo::Fn()
Ñóùåñòâóþò äâå ðàçíûå ïåðåìåííûå ñ îäíèì ëîêàëüíûì èìåíåì õ. Â îáëàñòè äåéñòâèÿ Foo
ñèìâîëè÷åñêîå èìÿ õ îçíà÷àåò Foo::õ.  îáëàñòè äåéñòâèÿ Bar ñèìâîëè÷åñêîå èìÿ õ îçíà÷àåò Âàr::õ.
Êîíå÷íî, äëÿ îòêðûòîé èëè çàùèùåííîé ïåðåìåííîé õ ýòî âûçîâåò íåâåðîÿòíóþ ïóòàíèöó, íî äëÿ
çàêðûòîé ïåðåìåííîé ïîäîáíîé äâóñìûñëåííîñòè íå áóäåò. Ïðèìåð Fn() ïîêàçûâàåò, êàêîé õàîñ
âîçíèêàåò ïðè ñêðûòèè îòêðûòîé èëè çàùèùåííîé ôóíêöèè êëàññà. Ïðè ïîïûòêå ñêðûòü îòêðûòóþ èëè
çàùèùåííóþ ôóíêöèþ õîðîøèé êîìïèëÿòîð C++ âûäàåò ïðåäóïðåæäåíèå.
Âèäèìîñòü ïåðåãðóæåííûõ è âèðòóàëüíûõ ôóíêöèé êëàññà
Åñëè â áàçîâîì êëàññå ôóíêöèÿ îáúÿâëåíà íåâèðòóàëüíîé, ïðåâðàùàòü åå â âèðòóàëüíóþ â ïðîèçâîäíîì
êëàññå íå ðåêîìåíäóåòñÿ. Îíà ïîâåäåò ñåáÿ íå òàê, êàê âèðòóàëüíàÿ ôóíêöèÿ, è áåçíàäåæíî çàïóòàåò
÷èòàòåëåé âàøåé ïðîãðàììû. Íî íà ñèòóàöèþ ìîæíî âçãëÿíóòü è ïîä äðóãèì óãëîì. Óäèâèòåëüíî, íî
ôàêò — êëþ÷åâîå ñëîâî virtual îáÿçàíî ïðèñóòñòâîâàòü òîëüêî â áàçîâîì êëàññå. Åñëè îíî


разработка сайта | php программист | Новости Интернет | Заказ авто, автомобили из США, машины из Америки