C++ ko'p darajali va ko'p tomonlama merosxo'rlik
Inheritance object-oriented dasturlash tilining asosiy xususiyatlaridan biridir. Bu dastur ishlab chiquvchilarga mavjud sinfdan yangi class olish imkonini beradi. Olingan sinf asosiy sinf (mavjud sinf) xususiyatlarini meros qilib oladi.
C++ dasturlashda merosning turli modellari mavjud.
C++ dasturlashda siz nafaqat asosiy sinfdan sinf olishingiz, balki olingan sinfdan ham sinf olishingiz mumkin. Merosning bu shakli ko'p darajali meros sifatida tanilgan.
class A {
... .. ...
};
class B: public A {
... .. ...
};
class C: public B {
... ... ...
};
Bu erda B klassi A tayanch sinfidan, C sinf esa olingan B sinfidan olingan.
#include <iostream>
using namespace std;
class A {
public:
void display() {
cout<<"Base class content.";
}
};
class B : public A {};
class C : public B {};
int main() {
C obj;
obj.display();
return 0;
}
Chiqish
Base class content.
Ushbu dasturda C sinfi B sinfidan (asosiy A sinfidan olingan) olingan.
C sinfining obj ob'ekti main() funksiyasida aniqlanadi.
display() funksiyasi chaqirilganda, A sinfidagi display() bajariladi. Buning sababi, C sinfida va B sinfida display() funksiyasi mavjud emas.
Kompilyator birinchi navbatda display() funksiyasini C sinfida qidiradi. function u yerda mavjud emasligi sababli, u B sinfidagi funksiyani qidiradi (chunki C B dan olingan).
Funksiya B sinfida ham mavjud emas, shuning uchun kompilyator uni A sinfida qidiradi (chunki B A dan olingan).
Agar display() funksiyasi C da mavjud bo'lsa, kompilyator A sinfidagi display() ni bekor qiladi ( member function overriding tufayli).
C++ dasturlashda sinf bir nechta ota-onadan olinishi mumkin. Masalan, A klassi Bat sutemizuvchi va WingedAnimal tayanch sinflaridan olingan. Bu mantiqqa to'g'ri keladi, chunki ko'rshapalak qanotli hayvon bilan bir qatorda sutemizuvchidir.
Multiple Inheritance

#include <iostream>
using namespace std;
class Mammal {
public:
Mammal() {
cout << "Mammals can give direct birth." << endl;
}
};
class WingedAnimal {
public:
WingedAnimal() {
cout << "Winged animal can flap." << endl;
}
};
class Bat: public Mammal, public WingedAnimal {};
int main() {
Bat b1;
return 0;
}
Chiqish
Mammals can give direct birth.
Winged animal can flap.
Ko'p meros bilan bog'liq eng aniq muammo funksiyani bekor qilish paytida yuzaga keladi.
Faraz qilaylik, ikkita asosiy sinf bir xil funksiyaga ega bo'lib, ular olingan sinfda bekor qilinmaydi.
Agar siz olingan sinf ob'ekti yordamida funksiyani chaqirishga harakat qilsangiz, kompilyator xatoni ko'rsatadi. Buning sababi, kompilyator qaysi funksiyani chaqirish kerakligini bilmaydi. Masalan,
class base1 {
public:
void someFunction( ) {....}
};
class base2 {
void someFunction( ) {....}
};
class derived : public base1, public base2 {};
int main() {
derived obj;
obj.someFunction() // Xato!
}
Bu muammoni qaysi funksiyani tayanch1 yoki tayanch2 sinfiga kiritishni belgilash uchun qamrovni aniqlash funksiyasi yordamida hal qilish mumkin.
int main() {
obj.base1::someFunction( ); // base1 sinfining funksiyasi deyiladi
obj.base2::someFunction(); // base2 sinfining funksiyasi deyiladi.
}
Agar bir nechta sinf asosiy sinfdan meros bo'lib o'tgan bo'lsa, u hierarchical inheritance deb nomlanadi. Ierarxik merosda bolalar sinflarida umumiy bo'lgan barcha xususiyatlar asosiy sinfga kiritilgan.
Masalan, Fizika, Kimyo, Biologiya fanlari fanidan olingan. Xuddi shunday, Dog, Cat, Horse hayvonlar sinfidan olingan.
class base_class {
... .. ...
}
class first_derived_class: public base_class {
... .. ...
}
class second_derived_class: public base_class {
... .. ...
}
class third_derived_class: public base_class {
... .. ...
}
// Ierarxik merosni ko'rsatish uchun C++ dasturi
#include <iostream>
using namespace std;
// asosiy sinf
class Animal {
public:
void info() {
cout << "I am an animal." << endl;
}
};
// olingan 1-sinf
class Dog : public Animal {
public:
void bark() {
cout << "I am a Dog. Woof woof." << endl;
}
};
// olingan 2-sinf
class Cat : public Animal {
public:
void meow() {
cout << "I am a Cat. Meow." << endl;
}
};
int main() {
// Dog sinfining ob'ektini yaratish
Dog dog1;
cout << "Dog Class:" << endl;
dog1.info(); // ota-ona sinf funksiyasi
dog1.bark();
// Cat sinfining ob'ektini yaratish
Cat cat1;
cout << "\nCat Class:" << endl;
cat1.info(); // ota-ona sinf funksiyasi
cat1.meow();
return 0;
}
Chiqish
Dog Class:
I am an animal.
I am a Dog. Woof woof.
Cat Class:
I am an animal.
I am a Cat. Meow.
Bu erda Dog va Cat sinflari Animal sinfidan olingan. Shunday qilib, ikkala olingan sinflar Animal sinfiga tegishli info() funksiyasiga kirishlari mumkin.
Virtual meros - bu C++ usuli bo'lib, nevara sinflari asosiy sinf a'zosi o'zgaruvchilarning faqat bitta nusxasini meros qilib olishiga ishonch hosil qiladi.
Keling, quyidagi sinf ierarxiyasini ko'rib chiqaylik.
Diamond Problem in Inheritance

Bu erda, Bat bir nechta sinflardan meros bo'lganda; Mammal va WingedAnimal bir xil asosiy sinfga ega; Animal , u asosiy sinfning bir nechta nusxalarini meros qilib olishi mumkin. Bu olmos muammosi sifatida tanilgan.
Virtual meros yordamida bu muammodan qochishimiz mumkin.
class Base {
... .. ...
};
class Derived1 : virtual public Base {
... .. ...
};
class Derived2 : virtual public Base {
... .. ...
};
class Derived3 : public Derived1, public Derived2 {
... ... ...
};
Bu yerda Derived1 va Derived2 Base dan virtual ravishda meros bo‘lib, Derived3 Derived1 va Derived2 dan meros bo‘lsa ham, Base a’zo o‘zgaruvchilarning faqat bitta to‘plamiga ega bo‘lishini ta’minlaydi.
#include <iostream>
using namespace std;
// typeName a'zo o'zgaruvchisi bilan asosiy sinf
class Animal {
private:
string species_name;
public:
// qabul qiluvchi konstruktor
// ishga tushirish uchun tur nomi
Animal(const string& name) : species_name(name) {
cout << "Animal constructor called" << endl;
}
void show_species() const {
cout << "This animal belongs to the species: " << species_name << endl;
}
};
// Animaldan virtual merosga ega WingedAnimal klassi
class WingedAnimal : virtual public Animal {
public:
// ishga tushiradigan konstruktor
// WingedAnimalning hayvon qismi
WingedAnimal(const string& name) : Animal(name) {
cout << "WingedAnimal constructor called" << endl;
}
};
// Hayvondan virtual merosga ega sutemizuvchilar sinfi
class Mammal : virtual public Animal {
public:
// ishga tushiradigan konstruktor
// Sutemizuvchilarning hayvoniy qismi
Mammal(const string& name) : Animal(name) {
cout << "Mammals constructor called" << endl;
}
};
// Bat sinfi WingedAnimal va Sutemizuvchilardan meros bo'lib o'tadi
class Bat : public WingedAnimal, public Mammal {
public:
// Bat konstruktor
// E'tibor bering, Animal's konstruktori faqat bir marta chaqiriladi
// virtual meros tufayli.
Bat() : Animal("Bat"), WingedAnimal("Bat"), Mammal("Bat") {
}
void show_info() {
cout << endl << "It's a unique animal! Here are some details:" << endl;
// tur_nomini ko'rsating
// umumiy a'zo o'zgaruvchini ko'rsatish
show_species();
}
};
int main() {
Bat my_bat;
my_bat.show_info();
return 0;
}
Chiqish
Animal constructor called
WingedAnimal constructor called
Mammals constructor called
It's a unique animal! Here are some details:
This animal belongs to the species: Bat
Ushbu misolda Bat klassi WingedAnimal va Mammal dan olingan bo'lib, ular o'z navbatida virtual meros yordamida Animal dan olingan.
Bu Bat namunasi yaratilganda va species_name "Bat" ga o'rnatilganda faqat bitta Animal asosiy sinf konstruktori chaqirilishini ta'minlaydi.
[!NOTE] Yuqoridagi dasturda, agar
virtualkalit so'zi ishlatilmagan bo'lsa,BatklassiAnimalsinfining a'zo o'zgaruvchisining bir nechta nusxalarini meros qilib oladi. Bu xatoga olib keladi.