Âûïîëíåíèå ñ ïîìîùüþ îïåðaöèè dynamiC_Cast ïîâûøaþùåãî ïðåîáðaçîâaíèя ðaâíîñèëüíî ïðîñòîìó ïðèñâaèâaíèþ (ïðè îòêðûòîì íañëåäîâaíèè):
Class B{ /* … */ };
Class C: publiC B{ /* … */ }; C* C = new C;
B* b = dynamiC_Cast(C); // Ýêâèâaëåíòíî B*b= ñ;
Понижающее преобразование
×aùå âñåãî îïåðaöèя dynamiC_Cast ïðèìåíяåòñя ïðè ïîíèæ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- íèåì RTTI (run-time type information) — «èíôîðìaöèè î òèïå âî âðåìя âûïîëíå- íèя ïðîãðaììû». Äëя òîãî ÷òîáû ïðîâåðêa äîïóñòèìîñòè ìîãëa áûòü âûïîëíåía, aðãóìåíò îïåðaöèè dynamiC_Cast äîëæåí áûòü ïîëèìîðôíîãî òèïa, òî åñòü èìåòü õîòя áû îäèí âèðòóaëüíûé ìåòîä (ñì. ñ. 205).
1 Åñëè âûðaæåíèå ðaâíî íóëþ, ðåçóëüòaò òaêæå ðaâåí íóëþ.
ПРИМЕЧАНИЕ
Äëя èñïîëüçîâaíèя RTTI íåîáõîäèìî ïîäêëþ÷èòü ê ïðîãðaììå çaãîëîâî÷íûé ôaéë
. Êðîìå òîãî, íåîáõîäèìî, ÷òîáû áûë óñòaíîâëåí ñîîòâåòñòâóþùèé ðåæèì êîì- ïèëяòîða.
Äëя ïîëèìîðôíîãî îáúåêòa ðåaëèçaöèя îïåðaöèè dynamiC_Cast âåñüìa ýôôåêòèâ- ía, ïîñêîëüêó ññûëêa ía èíôîðìaöèþ î òèïå îáúåêòa çaíîñèòñя â òaáëèöó âèðòó- aëüíûõ ìåòîäîâ, è äîñòóï ê íåé îñóùåñòâëяåòñя ëåãêî.
C òî÷êè çðåíèя ëîãèêè òðåáîâaíèå, ÷òîáû îáúåêò áûë ïîëèìîðôíûì, òaêæå îï- ðaâäaíî: âåäü åñëè êëaññ íå èìååò âèðòóaëüíûõ ìåòîäîâ, åãî íåëüçя áåçîïañíûì îáðaçîì èñïîëüçîâaòü, íå çíaя òî÷íûé òèï óêaçaòåëя. À åñëè òèï èçâåñòåí, èñ- ïîëüçîâaòü îïåðaöèþ dynamiC_Cast íåò íåîáõîäèìîñòè.
Ðåçóëüòaò ïðèìåíåíèя îïåðaöèè dynamiC_Cast n ónaçaòåëþ âñåãäa òðåáóåòñя ïðî- âåðяòü яâíûì îáðaçîì. Â ïðèâåäåííîì íèæå ïðèìåðå îïèñaí ïîëèìîðôíûé áaçî- âûé êëaññ B è ïðîèçâîäíûé îò íåãî êëaññ C, â êîòîðîì îïðåäåëåía ôóíêöèя f2. Äëя òîãî ÷òîáû âûçûâaòü åå èç ôóíêöèè demO òîëüêî â ñëó÷aå, êîãäa ïîñëåäíåé ïåðåäaåòñя óêaçaòåëü ía îáúåêò ïðîèçâîäíîãî êëañña, èñïîëüçóåòñя îïåðaöèя dynamiC_Cast ñ ïðîâåðêîé ðåçóëüòaòa ïðåîáðaçîâaíèя:
inClude inClude Class B{
publiC: virtual vOid f1(){};
};
Class C: publiC B{
publiC: vOid f2(){COut << "f2";};
};
vOid demO(B* p){
C* C = dynamiC_Cast(p); if (C) C->f2();
else COut << "Ïåðåäaí íå êëaññ C";
}
int main(){
B* b = new B;
demO(b); // Âûäaåòñя ñîîáùåíèå "Ïåðåäaí íå êëaññ C" C* C = new C;
demO(C); // Âûäaåòñя ñîîáùåíèå "f2" (ïðaâèëüíî) return 0;
}
Ïðè èñïîëüçîâaíèè â ýòîì ïðèìåðå âìåñòî dynamiC_Cast ïðèâåäåíèя òèïîâ â ñòè- ëå C, íaïðèìåð:
C* C = (C*) p;
ïðîêîíòðîëèðîâaòü äîïóñòèìîñòü îïåðaöèè íåâîçìîæíî, è åñëè óêaçaòåëü p ía ñaìîì äåëå íå ññûëaåòñя ía îáúåêò êëañña C, ýòî ïðèâåäåò ê îøèáêå.
Äðóãèì íåäîñòaòêîì ïðèâåäåíèя â ñòèëå C яâëяåòñя íåâîçìîæíîñòü ïðåîáða- çîâaíèя â ïðîèçâîäíûé âèðòóaëüíîãî áaçîâîãî êëañña, ýòî çaïðåùåíî ñèíòaêñè-
÷åñêè. C ïîìîùüþ îïåðaöèè dynamiC_Cast òaêîå ïðåîáðaçîâaíèå âîçìîæíî ïðè óñëîâèè, ÷òî êëaññ яâëяåòñя ïîëèìîðôíûì è ïðåîáðaçîâaíèå íåäâóñìûñëåííî. Ðaññìîòðèì ïðèìåð, â êîòîðîì âûïîëíяåòñя ïîíèxaþùåå ïðåîáðaçîâaíèå âèðòó- aëüíîãî áaçîâîãî nëañña:
inClude inClude
Class A{ // A
publiC: virtual ~A(){};}; // / \
Class B: publiC virtual A{}; // B C
Class C: publiC virtual A{}; // \ / Class D: publiC B, publiC C{}; // D vOid demO(A *a){
D* d = dynamiC_Cast(a); if (d) { … }
}
int main(){
D *d = new D; demO(d); return 0;
}
Do'stlaringiz bilan baham: |