Негізгі әдебиет- 5 [б.12,445-481] , 6 [б.6,159-177], 8[б.11,337-355]
Бақылау сұрақтары
1.Ерекшелік дегеніміз не?
2. try блогы және catch операторы не үшін керек?
3.Ерекшелік қандай ақпаратты сақтайды?
4.Функциялар, глобальды айнымалылар және ерекшелік механизмінің қолдау кластары.
5.Ерекшеліктегі конструкторлар мен деструкторлар.
14–Дәріс. Динамикалық идентификациясы және типтерді келтіру.
Динамикалық идентификациясы
Динамикалық типтерді келтіру
Полиморфизмді қолдайтын тілдерде компиляция кезінде объекттің типі белгісіз болу жағдайлары мүмкін, себебі бағдарламаның орындалуына дейін объекттің нақты табиғаты анықталмаған. С++ -те полиморфизм кластар иерархиясы, виртуалды функциялар мен базалық класс көрсеткіштері арқылы жүзеге асырылады. Осындай байланыс кезінде базалық класс көрсеткіші, базалық класс объектісіне сілтеу үшін, немесе осы базалық кластан туылған кез келген туынды объектісіне сілтеу үшін қолданылады. Әрбір уақыт мезетінде, базалық класс көрсеткіші сілтеме жасай алатын объект типін алдын ала анықтау мүмкіндігі бола бермейді. Мұндай жағдайларда объект типін анықтау бағдарлама орындалуы кезінде орындалуы керек, ал ол үшін типтің динамикалық идентификациясының механизмі қызмет етеді.
Объекттің типі туралы ақпаратты typeid ( объект) операторы арқылы алады, ол объекттің объектті типін сипаттайтын type-info тип объектіге сілтеме қайтарады. type-info класында келесі ашық мүшелер анықталған:
Bool operator ==(const type_info& объект) ; // типтерді салыстыру
Bool operator ! = (const type_info& объект) ; // типтерді салыстыру
Bool before (const type_info& объект) ;
Const char*name ( ); // оъект атына көрсеткіш
typeid операторы түрлі объект типтерін алуға мүмкіндік беруіне қарамастан, ол анағұрлым пайдалы болады, егер оның аргументі ретінде полиморфты базалық кластың көрсеткіші берілсе. Мұндай жағдайда, оператор автоматты түрде, көрсеткіш сілтеме жасайтын нақты объект типін қайтарады. Сөйтіп, typeid операторы көмегімен, бағдарламаның орындалуы кезінде, базалық класс көрсеткіш сілтеме жасайтын объект типін анықтауға болады. Сонымен қатар бұл сілтемелерге де қатысты болып табылады. Егер typeid операторының аргументі ретінде, полиморфты класс объектісіне сілтеме берілсе, онда оператор, сілтемесі бар объекттің нақты типін қайтарады. typeid операторын полиморфты емес класқа қолданғанда, базалық типтің көрсеткішін немесе сілтемесін алады.
Типтің динамикалық идентификациясы әрқашан қолдана берілмейді, бірақ мәндердің полиморфты типтерімен жұмыс істегенде, ол әртүрлі жағдайларда өңделетін объекттер типтерін анықтауға мүмкіндік береді.
// typeid операторын қолдану мысалы:
# include
# include
class Base
{ vertual void f ( ) { }; // класты полиморфты етеміз
};
сlass Der1 : public Base{…};
class Der2 : public Base {…};
int main(void)
{ int i;
Base *p,baseob; Der1 d1; Der2 d2;
cout «″ \n і айнымалыcының типі -бұл ″ « tepeid (i). name( ) « endl;
// полиморфты типтерді өңдеу
p=& baseob;
cout «″ р көрсеткіші тип объектісіне сілтеме жасайды ″;
cout «typeid (*p ) name ( ) «endl;
p=&d1;
cout «″р көрсеткіші тип объектісіне сілтеме жасайды ″«typeid (*p ) name ( );
p=&d2;
cout «″\n р көрсеткіші тип объектісіне сілтеме жасайды ″ «typeid (*p ) name ();
return 0 ;
}
Бағдарлама экранға келесі ақпаратты шығарады:
і айнымалысының типі - int
р көрсеткіші Base типті объектіге сілтеме жасайды
р көрсеткіші Der1 типті объектіге сілтеме жасайды ″;
р көрсеткіші Der2 типті объектіге сілтеме жасайды ″;
Объекттер функцияларға сілтеме бойынша берілетін жағдайда typeid операторының нақты қасиеті объекттің шын типін қайтарады, мысалы:
oid func ( Base & ref)
{ cout «″ ref –сілтеме объектіге мына түрдегі «typeid (ret ). name ( ) ;}
d1,d2 объектілері үшін шақыру кезінде олардың дұрыс идентификациясы орындалады: func(d1)және func(d2 ) сәйкесінше.
typeid операторының басты артықшылығы компиляция кезінде белгісіз объекттер типтерін идентификациялау мүмкіндігі болып табылады.
Экранда түрлі геометриялық фигураларды салу үшін арналған кластар иерархиясы анықтайтын бағдарлама мысалын қарастырайық. Иерархия басында төрт класты мұрагерленетін Shape абстрактты класы орналасқан: Line, Square,Rectangle және NullShape .
Функция generator ( ) объектіні туғызады және оған көрсеткішті қайтарады.Онда қандай объект құрылатынын, және rand ( ) - кездейсоқ сандық генераторы анықтайды. main ( ) функциясында, NullShape типті объекттерден басқа, экранда түрлі типті туындалған объектілер қортындысы жүзеге асырылған. Объекттер кездейсоқ туатындықтан, алдын ала, келесі қандай объект құрылатыны белгілі болмайды. Нәтижесінде, құрылатын объекттің типін анықтау үшін типтің динамикалық идентификациясы талап етіледі.
# include
# include
# include
class Shape
{ public : virtual void example( )=0;};
class Rectangle:public Shape
{public:void example( ){cout«″ Тікбұрыш\n″;} };
class Triangle :public Shape
{ public:void example ( ) { cout«″ \n Үшбұрыш \n ″;} };
class line : public Shape
{ public: void example( ) {cout «″\n Сызық\n″; } };
class NullShape
{ public :void example( ){ } };
// Shape класынан туындылар фабрикасы
Shape *generator ( )
{ switch (rand ( ) %4)
{ case о: return new Line ; case 1: return new Rectangle;
case 2:return new Triangle; case3:return new NullShape;
}
return Null;
} int main (void)
{ int i; Shape *p;
for (i=0;i <10;i++)
{ p=generator( ); // келесі объектіні құру
cout «typeid (*p ) name «endl
// объектіні салады, егер ол NullShape типті емес болса
if (typeid (*p )! =typeid (NullShape)) p--example( );
} return 0;
}
Typeid операторы үлгі-кластармен жұмыс істей алады. С++ тілінде жазылған бағдарламаны орындағанда типтер түрлері орындалады: нақты және нақты емес. Типтердің нақты түрленулері әрқашан программист қалауымен орындалады және ол үшін С++ тілінде мыналар бар: Си тілінен мұрагерленген типті келтіру операциясы, және С++ тіліне енгізілген функционалды жазба формасы; const_ cast, dynamic_cast, reinterpret_cast және
static_cast операциялары. Соңғы операциялар типтердің түрленулерінің анағұрлым сенімді операциялары болып табылады, және оларды барлық қажет жағдайларда қолданған жөн.
const_cast операциясы
Берілген операция const модификаторының әрекеттерін нөлге айналдыру үшін қолданылады:
const int i;
Int *p=const_cast(&i); // жай көрсеткішті аламыз
Жалпы жағдайда бұл операция келесі форматқа ие болады:
const_cast < T > (V),мұндағы Т типі V типі сияқты болу керек (әдетті бұл көрсеткіш). Операция Т типті нәтижені қайтарады. Бұл операцияның қажеттілігі функцияны жобалағанда const сияқты өзгермейтін параметрлерді сипаттау міндетті емес болумен шатастырылған, бірақ бұны істеу ұсынылады.С++ ережелері консттантты көрсеткішті жай көрсеткіш орнына беруге рұқсат етпейді .Сондықтан const_cast операциясы осы шектеуді айналып өту үшін енгізілген. Әрине, бұндай жағдайда функция берілетін көрсеткіш сілтеме жасайтын мәнді өзгертпеу керек.
Компиляция кезінде ( тақырып, ортаға жаз) типтердің түрленуі (static _cаst операциясы ) static _cаst операциясы компиляторымен орындалады және онсыз жұмыс істеуге болмайтын кезде ғана қолданылады. static_cаst операциясын қолданудың мысалын көрсеткіштің қажет типіне void* көрсеткішін түрлендіру деп атауға болады, бүтін типін есептеп шығу типіне келтіру және туыс типтердің басқа да түрленуі деп те атауға болады.
Бағдарламаны орындау кезіндегі типтердің түрленуі ( dynamic_cast) dynamic_ cast операциясы әдетте полиморфты объектілер үшін және виртуалды базалық кластардың түрленуін төмендету үшін қолданады. Бұл кезде, операция бағдарламаны орындау кезінде типтерді идентификациялау механизмін қолданады ( Run-Time Type Information, RTTI).
″ Өз қорқынышының мен тәуелсіздігіне ″ түрлену (reinterpret-cаst) жетекшілікті түрде сирек қолданылады, типтер арасында байланыссыз ″ экзотикалық ″ түрленуді орындау керек болғанда.
Достарыңызбен бөлісу: |