Все работает отлично.
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 îáÿçàíî
ïðèñóòñòâîâàòü
òîëüêî â áàçîâîì
êëàññå. Åñëè
îíî
|