Oddiy vorislik
Oddiy vorislik deb hosilaviy sinf bitta ota-onaga ega bo’ladigan vorislikka aytiladi. Sinfning turli usullari uchun vorislikning turli usullari mavjud – masalan, konstruktorlar va qiymat berish amali hosilaviy sinfda meros qoldirmaydi, destruktorlar meros qoldiradi. Sinflarni vorislash va bunda yuzaga keluvchi muammolarni misolda qarab chiqamiz.
monstr sinfiga hosilaviy sinf daemon ni yaratamiz. Bazaviy sinf yuqoridaga bo’limlardan qo’shilgan ba’zi usullar bilan keltirilgan:
enum color {red. green, blue};
// ---------- monstr sinfi -----------------
class monstr{
// ---------- Sinfning yashirin maydonlari:
int health, ammo;
color skin;
char *name;
public:
// ---------- Konstruktorlar:
monstr(int he = 100, int am = 10);
monstr(color sk);
monstr(char * nam);
monstr(monstr &M);
// ---------- Destruktor:
~monstr() {delete [ ] name;}
// ---------- Amallar:
monstr& operator ++(){
++health; return *this;
}
monstr operator ++(int){
monstr M(*this); health++; return M;
}
operator int(){
return health;
}
bool operator >(monstr &M){
if( health > M.health) return true;
return false;
}
const monstr& operator = (monstr &M){
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;
}
// ---------- Maydonga kirish usullari:
int get_health() const {return health;}
int get__ammo() const {return ammo;}
// ---------- Maydonlar qiymatlarini o’zgartiruvchi usullar:
void change_health(int he){ health = he;}
// ---------- Boshqa usullar:
void draw(int x, int y, int scale, int position):
};
// ---------- monstr sinfini amalga oshirish
monstr::monstr(in the, int am);
health (he), ammo (am), skin (red), name (0){}
monstr::monstr(monstr &M){
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;
}
monstr::monstr(color sk){
switch (sk){
case red : health = 100; ammo = 10; skin = red; name = 0; break;
case green : health = 100; ammo = 20; skin = green; name = 0; break;
case blue : health = 100; ammo = 40; skin = blue; name = 0; break;
}
}
monstr::monstr(char * nam){
name = new char [strlen(nam) + 1];
strcpy(name, nam);
health = 100; ammo = 10; skin = red;
}
void monstr::draw(int x, int y, int scale, int position)
{ /* ... monstr ni bekor qilish */ }
// ---------- daemon sinfi ----------
class daemon : public monstr{
int brain;
public:
// Конструкторы:
daemon(int br = 10){brain = br;};
daemon(color sk) : monstr (sk) {brain = 10;}
daemon(char * nam) : monstr (nam) {brain = 10;}
daemon(daemon &M) : monstr (M) {brain = M.brain;}
// ---------- Amallar:
const daemon& operator = (daemon &M){
if (&M == this) return *this;
brain = M.brain;
monstr::operator = (M);
return *this;
}
// ---------- Maydonlar qiymatlarini o’zgartiruvchi usullar:
void think();
// ---------- Boshqa usullar:
void draw(int х, int y, int scale, int position);
};
// ---------- daemon sinfini amalga oshirish
void daemon::think(){ /* ... */ }
void daemon::draw(int x, int y, int scale, int position)
{ /* ... daemon ni bekor qilish */ }
daemon sinfida brain maydoni va think usuli kiritilgan, xos konstruktor va qiymat berish amallari aniqlangan, hamda draw rasm chizish usuli qayta aniqlangan monstr sinfining birga maydonlari, amallari (qiymat berishdan tashqari) va get_health, get_ammo va change_health amallari daemon sinfida vorislanadi, destruktor esa jimlik bo’yicha shakllanadi.
Turli usullarni vorislik qoidalarini qaraymiz:
Konstruktorlar vorislanmaydi, shuning uchun hosila sinf o’z konstruktorlariga ega. Konstruktorlarni chaqirish tartibi quyidagi qoidalar bilan aniqlanadi.
Agar hosilaviy sinf konstruktorida bazaviy sinf konstruktorini oshkora chaqirish mavjud bo’lmasa, jimlik bo’yicha bazaviy sinf konstruktori avtomatik chaqiriladi (ya’ni parametrlarsiz chaqirish mumkin bo’lganini). daemon sinfi konstruktorlaridan birinchisida foydalaniladi.
Bir nechta darajalardan iborat shajara uchun bazaviy sinflar konstruktorlari eng yuqori bosqichdan boshlab chaqiriladi. Shundan so’ng obyektlar hisoblangan shunday sinf elementlarining konstruktorlari ularning sinfda e’lon qilish tartibida bajariladi keyin sinf konstruktori bajariladi.
Bir nechta bazaviy sinflar holida usulning konstruktorlari e’lon qilish tartibida chaqiriladi.
Qiymat berish amali vorislanmaydi, shuning uchun daemon sinfida oshkora aniqlash talab etiladi. Funksiya-amal yozuviga e’tibor bering, uni tanasida bazaviy sinfdagi qiymat berish funksiya-amalini oshkora chaqirish qo’llanilgan. Chaqiruv sintaksisini yaxshi tasavvur etish uchun operator kalit so’zi amal belgisi bilan birgalikda funksiya amal nomi kabi tavsiflash mumkin.
Bazaviy sinf funksiyalarni chaqirish bazaviy sinf funksiyalari va hosila sinf funksiyalari kodi parchalarini nusxalash afzalroq. Kod hajmini qisqartirishdan tashqari bu bilan dasturni takomilini soddalashtirishga erishiladi. O’zgarishlarni dasturning faqat bitta nuqtasiga kiritish talab etiladi, bu esa mumkin bo’lgan xatolar sonini qisqartiradi.
Destruktorlarni quyida vorislik qoidalari sanab o’tilgan:
Destruktorlar vorislanadi, va agar dasturchi hosilaviy sinfda destruktorni tavsiflamagan bo’lsa, u jimlik bo’yicha shakllanadi va barcha bazaviy sinflar destruktorlarini chaqiradi.
Konstruktorlardan farqli hosilaviy sinf destruktorni yozishda unda bazaviy sinflar destruktorlarini oshkora chaqirish talab etilmaydi, chunki bu avtomatik bajariladi.
Bir nechta bosqichlardan iborat sinflar shajarasi uchun destruktorlar konstruktorlar chaqiruviga qatiiy teskari tartibda chaqiriladi: dastlab sinf destruktori chaqiriladi, keyin – sinf elementlari destruktorlari, undan keyin bazaviy sinf destruktor chaqiriladi.
monstr sinfidan voris maydonlar hosilaviy sinf funksiyalariga kirish mumkin emas, chunki ular bazaviy sinfda private kabi aniqlangan. Agar daemon aniqlangan funksiyalarga bu maydonlar bilan ishlash talab etilsa yo ularni baza sinfida protected kabi tavsiflash yoki ularga monstr sinfidan funksiyalar yordamida murojaat qilish yoki ularni daemon da oldingi bo’limdagi kabi oshkora qayta aniqlash mumkin.
Usullarni vorisligi qaralayotganda daemon sinfda monstr sinfida o’sha nomda qayta aniqlanuvchi draw usuli aniqlangan (chunki turli personajlarni tasvirlash tabiiyki turlicha bajariladi). Shunday qilib, hosila sinfi baza sinfi holatini nafaqat to’ldirish, balki to’g’rilash mumkin. Hosila sinfi uchun qayta aniqlangan baza sinfining usuliga kirish ko’rinish sohasiga kirish amali yordamida aniqlashtirilgan nom orqali bajariladi.
Do'stlaringiz bilan baham: |