Перегрузка операции присваивания
Îïåðaöèя ïðèñâaèâaíèя îïðåäåëåía â ëþáîì êëaññå ïî óìîë÷aíèþ êaê ïîýëå- ìåíòíîå êîïèðîâaíèå. Ýòa îïåðaöèя âûçûâaåòñя êaæäûé ðaç, êîãäa îäíîìó ñóùå- ñòâóþùåìó îáúåêòó ïðèñâaèâaåòñя çía÷åíèå äðóãîãî. Åñëè êëaññ ñîäåðæèò ïîëя, ïaìяòü ïîä êîòîðûå âûäåëяåòñя äèíaìè÷åñêè, íåîáõîäèìî îïðåäåëèòü ñîáñòâåí- íóþ îïåðaöèþ ïðèñâaèâaíèя. ×òîáû ñîõðaíèòü ñåìaíòèêó ïðèñâaèâaíèя, îïåða- öèя-ôóíêöèя äîëæía âîçâðaùaòü ññûëêó ía îáúåêò, äëя êîòîðîãî îía âûçâaía, è ïðèíèìaòü â êa÷åñòâå ïaðaìåòða åäèíñòâåííûé aðãóìåíò — ññûëêó ía ïðèñâaè- âaåìûé îáúåêò.
COnst mOnstr& OperatOr = (COnst mOnstr &M){
// Ïðîâåðêa ía ñaìîïðèñâaèâaíèå:
if (&M == this) return *this; if (name) delete [] name;
if (M.name){
name = new Char [strlen(M.name) + 1]; strCpy(name, M.name);}
else name = 0;
health = M.health; ammO = M.ammO; skin = M.skin; return *this;
}
Âîçâðaò èç ôóíêöèè óêaçaòåëя ía îáúåêò äåëaåò âîçìîæíîé öåïî÷êó îïåðaöèé ïðèñâaèâaíèя:
mOnstr A(10), B, C;
C=B= A;
Îïåðaöèþ ïðèñâaèâaíèя ìîæíî îïðåäåëяòü òîëüêî êaê ìåòîä êëañña. Îía íå ía- ñëåäóåòñя.
Перегрузка операций new и delete
×òîáû îáåñïå÷èòü aëüòåðíaòèâíûå âaðèaíòû óïðaâëåíèя ïaìяòüþ, ìîæíî îïðå- äåëяòü ñîáñòâåííûå âaðèaíòû îïåðaöèé new è new[] äëя âûäåëåíèя äèíaìè÷åñêîé ïaìяòè ïîä îáúåêò è ìaññèâ îáúåêòîâ ñîîòâåòñòâåííî, a òaêæå îïåðaöèè delete è delete [] äëя åå îñâîáîæäåíèя.
Ýòè ôóíêöèè-îïåðaöèè äîëæíû ñîîòâåòñòâîâaòü ñëåäóþùèì ïðaâèëaì:
èì íå òðåáóåòñя ïåðåäaâaòü ïaðaìåòð òèïa êëañña;
ïåðâûì ïaðaìåòðîì ôóíêöèяì new è new[] äîëæåí ïåðåäaâaòüñя ðaçìåð îáúåê- òa òèïa size_t (ýòî òèï, âîçâðaùaåìûé îïåðaöèåé sizeOf, îí îïðåäåëяåòñя â çaãîëîâî÷íîì ôaéëå ); ïðè âûçîâå îí ïåðåäaåòñя â ôóíêöèè íåяâ- íûì îáðaçîì;
îíè äîëæíû îïðåäåëяòüñя ñ òèïîì âîçâðaùaåìîãî çía÷åíèя vOid*, äaæå åñëè
return âîçâðaùaåò óêaçaòåëü ía äðóãèå òèïû (÷aùå âñåãî ía êëaññ);
îïåðaöèя delete äîëæía èìåòü òèï âîçâðaòa vOid è ïåðâûé aðãóìåíò òèïa
vOid*;
îïåðaöèè âûäåëåíèя è îñâîáîæäåíèя ïaìяòè яâëяþòñя ñòaòè÷åñêèìè ýëåìåí- òaìè êëañña.
Ïîâåäåíèå ïåðåãðóæåííûõ îïåðaöèé äîëæíî ñîîòâåòñòâîâaòü äåéñòâèяì, âûïîë- íяåìûì èìè ïî óìîë÷aíèþ. Äëя îïåðaöèè new ýòî îçía÷aåò, ÷òî îía äîëæía âîç- âðaùaòü ïðaâèëüíîå çía÷åíèå, êîððåêòíî îáðaáaòûâaòü çaïðîñ ía âûäåëåíèå ïaìяòè íóëåâîãî ðaçìåða è ïîðîæäaòü èñêëþ÷åíèå ïðè íåâîçìîæíîñòè âûïîëíå- íèя çaïðîña (îá èñêëþ÷åíèяõ ðaññêaçûâaåòñя â ðaçäåëå «Îáðaáîòêa èñêëþ÷è- òåëüíûõ ñèòóaöèé» ía ñ. 222). Äëя îïåðaöèè delete ñëåäóåò ñîáëþäaòü óñëîâèå,
÷òî óäaëåíèå íóëåâîãî óêaçaòåëя äîëæíî áûòü áåçîïañíûì, ïîýòîìó âíóòðè îïå- ðaöèè íåîáõîäèìa ïðîâåðêa óêaçaòåëя ía íóëü è îòñóòñòâèå êaêèõ-ëèáî äåéñòâèé â ñëó÷aå ðaâåíñòâa.
Còaíäaðòíûå îïåðaöèè âûäåëåíèя è îñâîáîæäåíèя ïaìяòè ìîãóò èñïîëüçîâaòüñя â îáëañòè äåéñòâèя êëañña íaðяäó ñ ïåðåãðóæåííûìè (ñ ïîìîùüþ îïåðaöèè äî- ñòóïa ê îáëañòè âèäèìîñòè :: äëя îáúåêòîâ ýòîãî êëañña è íåïîñðåäñòâåííî — äëя ëþáûõ äðóãèõ).
Ïåðåãðóçêa îïåðaöèè âûäåëåíèя ïaìяòè ïðèìåíяåòñя äëя ýêîíîìèè ïaìяòè, ïî- âûøåíèя áûñòðîäåéñòâèя ïðîãðaììû èëè äëя ðaçìåùåíèя äaííûõ â íåêîòîðîé êîíêðåòíîé îáëañòè. Íaïðèìåð, ïóñòü îïèñûâaåòñя êëaññ, ñîäåðæaùèé óêaçaòåëü ía íåêîòîðûé îáúåêò:
Class Obj{… }; Class pObj{
… private:
Obj *p;
};
Ïðè âûäåëåíèè ïaìяòè ïîä îáúåêò òèïa pObj ñ ïîìîùüþ ñòaíäaðòíîé îïåðaöèè
new
pObj *p = new pObj;
ôaêòè÷åñêîå êîëè÷åñòâî áaéòîâ áóäåò ïðåâûøaòü sizeOf(pObj), ïîñêîëüêó new îáû÷íî çaïèñûâaåò â ía÷aëî âûäåëяåìîé îáëañòè åå ðaçìåð (äëя òîãî ÷òîáû ïða- âèëüíî îòðaáaòûâaëa îïåðaöèя delete):
Äëя íåáîëüøèõ îáúåêòîâ ýòè íaêëaäíûå ðañõîäû ìîãóò îêaçaòüñя âåñüìa çía÷è- òåëüíûìè. Äëя ýêîíîìèè ïaìяòè ìîæíî íaïèñaòü ñîáñòâåííóþ îïåðaöèþ new êëañña pObj, êîòîðaя áóäåò âûäåëяòü áîëüøîé áëîê ïaìяòè, a çaòåì ðaçìåùaòü â íåì óêaçaòåëè ía Obj. Äëя ýòîãî â îáúåêò pObj ââîäèòñя ñòaòè÷åñêîå ïîëå headOfFree, â êîòîðîì õðaíèòñя óêaçaòåëü ía ïåðâóþ ñâîáîäíóþ я÷åéêó áëîêa äëя ðaçìåùåíèя î÷åðåäíîãî îáúåêòa.
Íåèñïîëüçóåìûå я÷åéêè ñâяçûâaþòñя â ñïèñîê. ×òîáû íå çaíèìaòü ïaìяòü ïîä ïîëå ñâяçè, èñïîëüçóåòñя îáúåäèíåíèå (uniOn), ñ ïîìîùüþ êîòîðîãî îäía è òa æå я÷åéêa èñïîëüçóåòñя ëèáî äëя ðaçìåùåíèя óêaçaòåëя ía îáúåêò, ëèáî äëя ñâяçè ñî ñëåäóþùåé ñâîáîäíîé я÷åéêîé:
Class pObj{ publiC:
statiC vOid * OperatOr new(size_t size);
… private:
uniOn{
Obj *p; // Óêaçaòåëü ía îáúåêò
pObj *next; // Óêaçaòåëü ía ñëåäóþùóþ ñâîáîäíóþ я÷åéêó
};
statiC COnst int BLOCK_SIZE; // Ðaçìåð áëîêa
// Çaãîëîâîê ñïèñêa ñâîáîäíûõ я÷ååê: statiC pObj *headOfFree;
};
vOid * pObj::OperatOr new(size_t size){
// Ïåðåíaïðaâèòü çaïðîñû íåâåðíîãî êîëè÷åñòâa ïaìяòè
// ñòaíäaðòíîé îïåðaöèè new:
if (size != sizeOf(pObj)) return ::OperatOr new(size);
pObj *p = headOfFree; // Óêaçaòåëü ía ïåðâóþ ñâîáîäíóþ я÷åéêó
// Ïåðåìåñòèòü óêaçaòåëü ñïèñêa ñâîáîäíûõ я÷ååê: if (p) headOfFree=p -> next;
// Åñëè ñâîáîäíîé ïaìяòè íåò, âûäåëяåì î÷åðåäíîé áëîê: else {
pObj *newblOCk = statiC_Cast
1 (::OperatOr new(BLOCK_SIZE * sizeOf(pObj)));
// Âñå я÷åéêè ñâîáîäíû, êðîìå ïåðâîé (îía áóäåò
// çaíяòa), ñâяçûâaåì èõ:
fOr (inti= 1; i< BLOCK_SIZE – 1; ++i) newblOCk[i].next = &newblOCk[i + 1];
newblOCk[BLOCK_SIZE – 1].next = 0;
// Óñòaíaâëèâaåì ía÷aëî ñïèñêa ñâîáîäíûõ я÷ååê: headOfFree = &newblOCk[1];
p = newblOCk;
}
return p; // Âîçâðaùaåì óêaçaòåëü ía âûäåëåííóþ ïaìяòü
}
Ïåðåãðóæåííaя îïåðaöèя new íañëåäóåòñя, ïîýòîìó îía âûçûâaåòñя äëя ïðîèç- âîäíûõ îáúåêòîâ. Åñëè èõ ðaçìåð íå ñîîòâåòñòâóåò ðaçìåðó áaçîâîãî (a òaê, ñêî- ðåå âñåãî, è åñòü), ýòî ìîæåò âûçâaòü ïðîáëåìû. ×òîáû èõ èçáåæaòü, â ía÷aëå îïå- ðaöèè ïðîâåðяåòñя ñîîòâåòñòâèå ðaçìåðîâ. Åñëè ðaçìåð îáúåêòa íå ðaâåí òîìó, äëя êîòîðîãî ïåðåãðóæåía îïåðaöèя new, çaïðîñ ía âûäåëåíèå ïaìяòè ïåðåäaåòñя ñòaíäaðòíîé îïåðaöèè new.
 ïðîãðaììå, èñïîëüçóþùåé êëaññ pObj, äîëæía ïðèñóòñòâîâaòü èíèöèaëèçaöèя åãî ñòaòè÷åñêèõ ïîëåé (ñòaòè÷åñêèå ïîëя ðaññìaòðèâaëèñü ía ñ. 186):
pObj *pObj::headOfFree; // Óñòaíaâëèâaåòñяâ0 ïî óìîë÷aíèþ COnst int pObj::BLOCK_SIZE = 1024;
Êaê âèäíî èç ýòîãî ïðèìåða, ïîìèìî ýêîíîìèè ïaìяòè äîñòèãaåòñя åùå è âûñî- êîå áûñòðîäåéñòâèå, âåäü â áîëüøèíñòâå ñëó÷aåâ âûäåëåíèå ïaìяòè ñâîäèòñя ê íåñêîëüêèì ïðîñòûì îïåðaòîðaì.
Åñòåñòâåííî, ÷òî åñëè îïåðaöèя new ïåðåãðóæåía, òî æå ñaìîå äîëæíî áûòü âû- ïîëíåíî è äëя îïåðaöèè delete (íaïðèìåð, â íaøåì ñëó÷aå ñòaíäaðòíaя îïåðaöèя delete íå íaéäåò â ía÷aëå îáúåêòa âåðíîé èíôîðìaöèè î åãî ðaçìåðaõ, ÷òî ïðèâå- äåò ê íåîïðåäåëåííîìó ïîâåäåíèþ ïðîãðaììû).
 ðaññìîòðåííîì ïðèìåðå îïåðaöèя delete äîëæía äîáaâëяòü îñâîáîæäåííóþ я÷åéêó ïaìяòè ê ñïèñêó ñâîáîäíûõ я÷ååê:
vOid pObj::OperatOr delete(vOid * ObjTODie, size_t size){ if (ObjTODie == 0) return;
if (size != sizeOf(pObj)){
1 Çäåñü èñïîëüçîâaíî яâíîå ïðåîáðaçîâaíèå òèïa ñ ïîìîùüþ îïåðaöèè statiC_Cast. Î íåì ðaññêaçûâaåòñя â ðaçäåëå «Îïåðaöèя static_cast» ía ñ. 237.
::OperatOr delete(ObjTODie); return;
}
pObj *p = statiC_Cast
(ObjTODie); p->next = headOfFree;
headOfFree = p;
}
 îïåðaöèè delete âûïîëíåía ïðîâåðêa ñîîòâåòñòâèя ðaçìåðîâ îáúåêòîâ, aíaëî- ãè÷íaя ïðèâåäåííîé â îïåðaöèè new.
Do'stlaringiz bilan baham: |