27
Дәрістің мазмұны:
базалық класс. Туынды класс. Виртуалды базалық
кластар.
Туынды класс бір базалық кластан артық класқа мұра ете алатын екі
әдіс бар. Біріншіден туынды класс көп деңгейлі кластар иерархиясын құра
отырып, базалық ретінде басқа туынды класс үшін қолдануға болады.
Екіншіден, туынды класс бір базалық кластан артық класты тікелей мұра ете
алады. Класс туындыға базалық класс ретінде қолданылса, өз кезегінде басқа
туынды класс үшін базалық болса, онда барлық үш кластың конструкторлары
мұрагерлік ретімен шақырылады. Деструкторлар кері тәртіппен шақырылады.
Егер туынды класс бірнеше базалық кластың мұрасына тікелей ие болса,
онда мынадай кеңейтілу қолданылады:
class туынды _класс _аты:as базалық_ класс_аты1;
as базалық_класс_аты N
{ туынды класс денесі }
Мұндай жағдайда конструкторлар туынды кластың хабарламасында
берілген тәртіп бойынша солдан оңға қарай орындалады. Егер осындай мұраға
ие болу әдісі кезінде базалық кластардың конструкторларына
аргументтерді
беру қажет болса, туынды класс оларды туынды класс конструкторларының
хабарламасының кеңейтілген формасын қолдана отырып береді:
туынды_класс_конструкторы (аргументтер_тізімі);
базалық_класс1_аты (аргументтер_тізімі);
базалық_класс 2_аты (аргументтер_ тізімі);
....., базалық_класс N_аты (аргументтер_тізімі)
{туынды класс конструкторының денесі }
Егер туынды класс кластар иерархиясының мұрасына ие болса, әрбір
туынды класс тізбекті алдыңғы базалық класқа
барлық қажет аргументтерді
береді. Бұл ережені орындамау программаны компиляциялау кезінде қателік
туғызады.
Қызметші сөз сlass көмегімен анықталған класс базалық сияқты туынды
бола алады. Мұндай жағдайда үнсіздік бойынша класс мүшелері жабық болып
табылады.
Қызметші сөз Struct көмегімен анықталған кластар базалық сияқты
туынды да бола алады, және үнсіздік бойынша класс мүшелері ашық болып
табылады.
Қызметші сөз union бар класс белгілі бір класқа қатысты базалық та,
туынды да бола алмайды. Туынды класс кезіндегі жағдайларды түсіндіретін
бағдарламаны қарастырайық:
-
басқадан туынды класс мұрасына ие болады;
-
екі базалық кластың мұрасына тікелей ие болады;
28
-
бірнеше базалық кластың мұрасына тікелей ие болады.
# include
class Base1
{ int a;
public: Base1(int x) {a=x; }
int geta() { return a; }
} ;
class Der1:public Base1
{ int b;
public: Der1(int x,int y):Base1(y)
{ b=x;}
int get b() {return b;}
};
class Der2 :public Der1
{ int c;
public:Der2 (int x,int y,int z):Der1(y,z)
{ c=x;}
void show()
{ cout«geta ()« ´ ´«getb()«´ ´ «getc()«endl;}
};
int main (void)
{ Der2 obj(1,2,3);
obj.show( ) ;
cout « obj.geta ( ) «´ ´« obj.getb( ) « endl ;
return 0;}
Базалық кластың ашық мүшелерінің мұрасына ие болғанда олар туынды
кластың ашық мүшелеріне айналады. Сондықтан, егер geta Base1 класына
мұрагерленсе, онда get a ( ) функциясы Der1 класының ашық мүшесіне және
кейін Der2 класының ашық мүшесіне айналады.
Туынды класс тікелей екі базалық класқа мұрагерленетін алдыңғы
бағдарламаның қайта өндірілген нұсқасын қарастырайық:
# include
class Base1
{ int a;
public: Base1(int x) {a=x; }
int geta () { return a; }
} ;
class Base2
{ int b;
public: Base2 (int x) {b=x;}
int getb () {return b;}
29
};
class Der :public Base1, public Base2
{int c;
public: Der(int x,int y,int z):Base1(z),Base2(y)
{ c=x;}
void show ()
{ cout «geta () « ´ ´«getb() «´ ´ «getc()«endl;}
};
int main (void)
{Der obj (1,2,3);
obj.show ( ) ;
return 0;}
Келесі бағдарламада туынды класс тікелей бірнеше базалық класқа
мұрагерленетін кезде конструкторлар мен деструкторлар шақырылатын
тәртіпті көрсетейік:
# include
class Base1
{ int a;
public: Base1() { cout « Base1 класс конструкторының жұмысы\ n"; }
~ Base1() { cout « " Base1 класс деструкторының жұмысы\ n"; }
int x) {a=x; }
int geta () { return a; }
} ;
class Base2
{ int b;
public: Base2 () { cout «" Base2 класс конструкторының жұмысы\ n"; }
~ Base 2(){ cout «" Base2 класс деструкторының жұмысы\ n"; }
};
class Der :public Base1, public Base2
public:Der() { cout«" Der класс конструкторының жұмысы\ n"; }
~Der () { cout «" Der класс деструкторының жұмысы\ n"; }
};
int main (void)
{ Der obj;
return 0;}
Бірнеше базалық кластар тікелей мұрагерленсе, конструкторлар
тізіммен берілетін тәртіпте солдан оңға қарай шақырылады, ал
конструкторлар кері тәртіпте, сондықтан бағдарлама мынаны экранға
шығарады:
-
Base1 класының конструкторының жұмысы;
-
Base2 класының конструкторының жұмысы;
30
-
Der класының конструкторының жұмысы;
-
Der
класының деструкторының жұмысы;
-
Base2 класының деструкторының жұмысы;
-
Base1 класының деструкторының жұмысы.
Виртуалды базалық кластар.
Туынды класс бір базалық класқа бір реттен артық жанама түрде
мұрагерленсе және базалық класс барлық туынды кластар үшін виртуалды
сияқты мұрагерленсе туынды класс объектісіндегі базалық кластың екі
көшірмесінің пайда болуын болдырмауға болады. Мұндай мұрагерлік
базалық класқа мұрагерленетін кез келген келесі туынды класта базалық
кластың екі (немесе одан да көп ) көшірмелерінің
пайда болуына жол
бермейді. Мұндай жағдайда базалық класқа өту жолының спецификаторының
алдына virtual шешуші сөзін қою керек.
С++ тілінің синтаксисі туынды класқа базалық класты тікелей бірнеше
рет беруге тыйым салады:
Class A {…. };
Class B: A,A{….}; // қате
Сонымен бірге базалық класты жанама түрде беруге тыйым салынады:
Class A {….};
Class B: public A {….}; // қате
Class C: public A, public B {….} // қате
«Қарапайым» мұрагерлік кезінде туынды класс объектісінің құрамына
базалық кластың ішкі объектісі кіреді, ал виртуалды мұрагерлік кезінде
туынды класс объектісінің құрамына виртуалды
базалық кластың ішкі
объектісіне жасырын көрсеткіші енеді, оны компилятор виртуалды базалық
кластан мұрагерленген мүшелерге жол беруге арналған объектімен жұмыс
барысында айқынсыз қолданады.
Сlass A {…. };
Class B: virtual public A {….};
Class C: virtual public A, public B // осылай жазуға болады
{….};
Мысалы, Der3 класында Base класының екі көшірмесін болдырмайтын
виртуалды базалық класс қолданылады:
# include
class Base
{public : int i ; };
31
class Der1 : vertual public Base
{public: int j ; };
class Der2 : vertual public Base
{public: int k ; };
class Der3 : publicDer1, public Der2
{public: int f( ){return i*j*k;}} ;
int main(void)
Der3 obj ;
//Бір мағынасыздық
болмайды, себебі Base класының тек бір көшірмесі
ұсынылған.
obj. i=10; obj.j=3; obj.k=5;
cout « ″ нәтежиесі″ « obj .f( ) « endl;
return 0;
}
Бақылау сұрақтары:
1)
Кластар иерархиясы қалай анықтауға болады?
2)
Объектер иерархиясында хабарламаларды өңдеудің сұлбасы қандай?
3)
Егер базалық кластың мүшелері жаңа қайта туынды класта
анықталған атаулардың мұрасына ие болса, онда оларға туынды кластан
рұқсат беріле ме?
4)
Рұқсат етудің қандай спецификаторларын объектілер мұрагерлік
иерархиясында хабарламаларды өңдегенде қолдана алады?
5)
Қандай жағдайларда виртуалды класс
механизмдеріне қатынас
жасалады?
Достарыңызбен бөлісу: