inheritance c
Значение на наследяването в C ++ с примери:
Наследяването е една от най-важните характеристики на обектно-ориентираното програмиране.
Наследяването е техниката, чрез която един клас придобива свойствата и методите на другия клас. По този начин можем да използваме повторно написания и проверен код. Класът, който придобива свойствата на друг клас, се нарича подклас или производен клас или дъщерен клас.
Класът, чиито свойства се придобиват, се нарича основен клас или родителски клас или суперклас. Когато един клас придобие или наследи друг клас, тогава всички свойства и методи на базовия клас са налични за производния клас, така че да можем да използваме този код повторно.
=> Посетете тук, за да научите C ++ от нулата.
алгоритъм за сортиране на черупки c ++
Какво ще научите:
- Защо се нуждаем от наследство?
- Начини на наследяване
- Ред на конструкторите / деструкторите по наследство
- Видове наследяване
- Наследяване на шаблон
- Състав
- Как трябва да решим между състава и наследството?
- Заключение
- Препоръчително четене
Защо се нуждаем от наследство?
Помислете за група превозни средства като кола, автобус, джип и др. Всяко от тези превозни средства ще има свойства и методи, както е посочено в диаграмата по-долу.
Ако от нас се изисква да внедрим отделни класове за горните превозни средства, можем да видим, че и във всичките три класа ще трябва да напишем един и същ код, тъй като и трите типа превозни средства имат повече или по-малко същите свойства. Това ще направи нашата програма неефективна и тромава, тъй като ще има много дублирани кодове.
Вместо да напишем дублиран код, както по-горе, можем да внедрим функцията за наследяване, за да предотвратим дублирането на кода, а също така да напишем една част от кода и да го използваме във всичките три класа. Това е изобразено нагледно по-долу.
На горната фигура дефинирахме основен клас „Превозни средства“ и от този клас изведохме класовете Car, Bus и Jeep. Общите методи и свойства са част от класа Vehicles сега. Тъй като други класове са получени от класа Vehicles, всички класове придобиват тези методи и свойства.
Следователно, просто трябва да напишем общия код само веднъж и всичките три класа; Автомобилът, автобусът и джипът ще го придобият.
По този начин основното предимство, което получаваме чрез наследяване на съществуващите класове или проектиране на механизъм за наследяване, е повторната употреба на кода.
Допълнително четене = >> Урок за наследяване на Java
Общият формат за наследяване на клас е:
class derived_classname: access_specifier base_classname { };
Тук ' производно_класно име 'Е името на производния клас,' access_specifier 'Е режимът на достъп, т.е. публичен, защитен или частен, в който производният клас трябва да наследи базовия клас и' производно_класно име ”Е името на базовия клас, от който наследява производния клас.
Начини на наследяване
„Access_specifier“, показан в горната декларация за наследяване, може да има своите стойности, както е показано по-долу.
В зависимост от указания access_specifier, когато наследяваме класа, имаме различни режими на наследяване, изброени по-долу.
Публично наследство
Общ синтаксис
class sub_class : public parent_class
Когато е зададен спецификатор за публичен достъп, публичните членове на базовия клас се наследяват като публични, докато защитените членове са защитени. Частните членове остават частни. Това е най-популярният начин на наследяване.
Частно наследство
Общ синтаксис
class sub_class : parent_class
Частното наследство не наследява нищо. Когато се използва спецификатор за частен достъп, публичните и защитени членове на базовия клас също стават частни.
кой тип тест се използва, за да се провери дали всички програми в дадено приложение работят заедно правилно?
Защитено наследство
Общ синтаксис
class sub_class:protected parent_class
Когато се използва спецификатор на защитен достъп, публичните и защитените членове на базовия клас стават защитени членове в производния клас.
Имайте предвид, че когато използваме спецификатор за частен достъп за базовия клас, никой от членовете на базовия клас не се наследява. Всички те стават частни в производния клас.
По-долу е дадено табличното представяне на всички режими на достъп и тяхното тълкуване за наследяване.
Производен клас -> Базов клас | Частен | Публично | Защитена |
---|---|---|---|
Частен | Не се наследява | Не се наследява | Не се наследява |
Публично | Частен | Публично | Защитена |
Защитена | Частен | Защитена | Защитена |
Ред на конструкторите / деструкторите по наследство
Когато класовете се наследяват, конструкторите се извикват в същия ред като класовете се наследяват. Ако имаме основен клас и един производен клас, който наследява този основен клас, тогава конструкторът на базовия клас (независимо дали по подразбиране или параметризиран) ще бъде извикан първо, последван от конструктора на производен клас.
Следващата програма демонстрира реда на конструкторите при наследяване. Имаме Base клас “Base”, който има конструктор по подразбиране и параметризиран конструктор. Ние извличаме клас от този, наречен „Изведен“, който също има един по подразбиране и друг параметризиран конструктор.
Резултатът от тази програма показва реда, в който са извикани конструкторите.
#include using namespace std; //order of execution of constructors in inheritance class Base { int x; public: // default constructor Base() { cout Изход:
Конструктор по подразбиране на базовия клас
Конструктор по подразбиране на базовия клас
Изведен конструктор на клас по подразбиране
Параметризиран конструктор на основен клас
Изведен параметризиран конструктор на клас
Виждаме, че след създаването на обекта на базовия клас създаваме производен обект на клас с конструктор по подразбиране. Когато този обект е създаден, първо се извиква конструктор по подразбиране на базовия клас и след това се изпълнява конструктора на производен клас.
По същия начин, когато производният обект на клас се създава с помощта на параметризирания конструктор, първо се извиква параметризираният конструктор на базовия клас и след това се извиква конструктора на производен клас.
Имайте предвид, че ако в базовия клас нямаше параметризиран конструктор, тогава конструкторът по подразбиране би бил извикан дори за конструиране на параметризирания производен обект на клас.
Но остава въпросът защо се извиква конструктор на базовия клас при конструиране на производни обекти на клас?
Знаем, че конструктор се използва за създаване на обекти от класа и за инициализиране на членовете на класа. Когато деривираният обект на клас е създаден, неговият конструктор има контрол само върху производните членове на класа.
Производният клас обаче наследява и членовете на базовия клас. Ако се извика само конструкторът на производен клас, тогава членовете на базовия клас, наследени от производния клас, няма да бъдат инициализирани правилно.
В резултат на това целият обект няма да бъде създаден ефективно. Това е причината, поради която всички конструктори на базовия клас се извикват първо, когато се създаде обект на производен клас.
Видове наследяване
В зависимост от начина, по който е извлечен класът или колко базови класа наслежда клас, имаме следните типове наследяване, както е показано на фигурата по-долу.
Ще разгледаме всеки от тези типове в следващия урок на тема „Видове наследяване“.
Наследяване на шаблон
Когато нашето внедряване включва шаблони, тогава трябва да наследим или да извлечем от класове шаблони и използваме наследяване на шаблони там.
Нека директно да преминем към пример за програмиране, за да разберем по-добре наследството с помощта на шаблони.
#include using namespace std; //template inhertance templateclass basecls_Template { public: T value; basecls_Template(T value) { this->value = value; } void displayVal() { cout << value << endl; } }; //derived class inherits basecls_Template class derivedcls_Child : public basecls_Template { public: derivedcls_Child(/* no parameters */): basecls_Template( 0 ){ // default char is NULL; } derivedcls_Child(char c): basecls_Template( c ) { ; } void displayVal_drvd() { displayVal(); } }; int main() { basecls_Template obj( 100 ); derivedcls_Child obj1( 'A' ); cout<<'basecls_Template obj = '; obj.displayVal(); // should print '100' cout< Изход:
basecls_Template obj = 100
derivacls_Child obj1 (наследено от basecls_Template = A
В горната програма имаме шаблон с име basecls_Template, който дефинира шаблона на класа за базовия клас. След това дефинираме клас, полученcls_Child, който искаме да извлечем от клас на шаблон.
Но имайте предвид, че класът basecls_Template е само тип, а не клас. Следователно, не можем да извлечем класа, произведенcls_Child от този шаблон.
Следователно, ако декларираме детския клас като:
class derivedcls_Child : public basecls_Template
Това ще доведе до грешка. Причината да е basecls_Template е тип данни, а не клас. По този начин, за да наследим членовете на basecls_Template, първо трябва да го създадем, преди да извлечем от него.
Следователно горното твърдение, Клас, получен от cls_Child: public basecls_Template работи добре.
В това изявление ние създадохме инстанция на шаблона basecls_Template в шаблон на клас знаци. След като използваме този клас на инстанциран шаблон, тогава другите неща, които следват създаването и използването на обекти, съвпадат с обичайното работещо наследяване.
Състав
Досега сме виждали всичко за наследствените отношения. Наследството основно показва вида на връзките, при които връзката показва част. Например, змия е вид влечуго. Можем също да кажем, че влечугите са част от класа на животните.
В заключение наследството показва 'Е' вид връзки, при които можем да кажем, че производният клас е част от базовия клас.
Можем също да представим взаимоотношенията като цяло. Например, ако кажем, че класът на заплатите е част от класа на служителите, тогава не го представяме правилно. Знаем, че служителите имат заплата. По този начин е по-удобно да се каже „Служителят има заплата“.
По същия начин, ако вземем за пример клас Vehicles, можем да кажем, че Vehicle има двигател или Vehicle има шаси. Така всички тези взаимоотношения изобразяват 'ИМА' връзки, които представляват цял обект, съдържащ се в друг клас. Това се определя като Състав .
Връзките, изобразени чрез композиция, са зависими една от друга. Например, шаси не може да съществува без превозно средство. По същия начин Заплатата не може да съществува без служител.
Можем да представим схематично състава, както е показано по-долу:
Съставът е наречен също Contention. В горното представяне показахме родителски клас. За разлика от наследяването, ние включваме обект на детски клас вътре в родителския клас. Това е ограничение или състав.
какво е .swf файл
Нека вземем пример за програмиране, за да разберем това.
#include using namespace std; //Composition example //Child class - address class Address { public: string houseNo, building, street, city, state; //Initialise the address object Address(string houseNo,string building,string street, string city, string state) { this->houseNo = houseNo; this->building = building; this->street = street; this->city = city; this->state = state; } }; //Parent class - Employee class Employee { private: Address* address; //composition->Employee has an address public: int empId; string empName; Employee(int empId, string empName, Address* address) { this->empId = empId; this->empName = empName; this->address = address; } void display() { cout< Изход:
10001 Вед
A-101 Сребърни извори Aundh Pune Maharashtra
В този пример имаме родителски клас Служител и детски клас Адрес. Вътре в родителския клас Employee сме декларирали указател към класа Address и също инициализираме този обект в конструктора Employee. По този начин ние изобразяваме връзката, че служителят има адрес, който е състав.
Как трябва да решим между състава и наследството?
Композицията и наследяването изобразяват връзките между класовете. Докато наследството изобразява връзката “IS-A”, композицията изобразява връзката “HAS-A”.
Сега въпросът е, че кога трябва да използваме наследство и кога трябва да използваме композиция? Всъщност не можем да вземем решение за точните ситуации, когато трябва да използваме някоя от тях. Това е така, защото всеки има своите предимства и недостатъци.
И двете насърчават повторната употреба на кода. Наследяването може да направи кода обемен, тъй като решенията стават сложни, но в същото време също така ни позволява да разширим съществуващия код. По този начин трябва да използваме наследяване, когато нашето изискване е да модифицираме и използваме свойствата и метода на друг клас вътре в новия клас.
С други думи, когато искаме да добавим повече свойства и да разширим съществуващия клас. От друга страна, когато не искаме да модифицираме свойствата и поведението на друг клас, а просто го използваме вътре в класа, отиваме за композиция.
По този начин най-доброто решение е дали да се използва композиция или наследяване ще бъде взето чрез претегляне на плюсовете и минусите на двете техники за конкретната ситуация.
= >> Прочетете също Composition в Java
Заключение
Така стигнахме до края на нашата тема за наследяването. Виждали сме различни начини на наследяване. Видяхме и видовете наследяване, които ще изследваме в следващия урок. Научихме за реда на конструкторите, които се изпълняват в случай на наследяване.
Проучихме и за шаблони и наследяване. Трябва да създадем инстанция на шаблон, преди да можем да го използваме при наследяване, тъй като самият шаблон е тип данни и не можем да наследяваме от тип данни.
Композицията е друг тип класова връзка и първо трябва да знаем точната ситуация и след това само ние можем да решим дали да използваме композиция или наследство.
В нашия предстоящ урок ще видим повече за видовете наследяване.
=> Внимавайте тук за простият сериал за обучение на C ++.
Препоръчително четене
- Видове наследяване в C ++
- Полиморфизъм по време на изпълнение в C ++
- Приятелски функции в C ++
- Използване на Selenium Select Class за работа с падащи елементи на уеб страница - Урок № 13 за Selenium
- Класове и обекти в C ++
- Статично в C ++
- Урок за тръби на Unix: Тръби в програмирането на Unix
- Урок за интерфейс на Java и абстрактен клас с примери