inheritance c
Importance de l'héritage en C ++ avec des exemples:
L'héritage est l'une des caractéristiques les plus importantes de la programmation orientée objet.
L'héritage est la technique par laquelle une classe acquiert les propriétés et les méthodes d'une autre classe. De cette façon, nous pouvons réutiliser le code qui est déjà écrit et vérifié. La classe qui acquiert les propriétés d'une autre classe est appelée sous-classe ou classe dérivée ou classe enfant.
La classe dont les propriétés sont acquises est appelée la classe de base ou la classe parente ou la superclasse. Lorsqu'une classe acquiert ou hérite d'une autre classe, toutes les propriétés et méthodes de la classe de base sont disponibles pour la classe dérivée, afin que nous puissions réutiliser ce code.
=> Visitez ici pour apprendre le C ++ à partir de zéro.
questions et réponses sur les tests d'assurance qualité
Ce que vous apprendrez:
- Pourquoi avons-nous besoin d'un héritage?
- Modes d'héritage
- Ordre des constructeurs / destructeurs en héritage
- Types d'héritage
- Héritage de modèle
- Composition
- Comment décider entre composition et héritage?
- Conclusion
- lecture recommandée
Pourquoi avons-nous besoin d'un héritage?
Considérez un groupe de véhicules comme une voiture, un bus, une jeep, etc. Chacun de ces véhicules aura les propriétés et les méthodes indiquées dans le diagramme ci-dessous.
Si nous devons implémenter des classes individuelles pour les véhicules ci-dessus, nous pouvons voir que dans les trois classes, nous devrons écrire le même code car les trois types de véhicules présentent plus ou moins les mêmes propriétés. Cela rendra notre programme inefficace et encombrant car il y aura beaucoup de code en double.
Au lieu d'écrire un code dupliqué comme ci-dessus, nous pouvons implémenter la fonctionnalité d'héritage pour empêcher le code de se dupliquer et également écrire un seul morceau de code et l'utiliser dans les trois classes. Ceci est représenté sous forme d'image ci-dessous.
Dans la figure ci-dessus, nous avons défini une classe de base «Véhicules» et dérivé les classes Voiture, Bus et Jeep de cette classe. Les méthodes et propriétés courantes font désormais partie de la classe Vehicles. Comme les autres classes sont dérivées de la classe Vehicles, toutes les classes acquièrent ces méthodes et propriétés.
Par conséquent, nous avons juste besoin d'écrire le code commun une seule fois et les trois classes; Car, Bus et Jeep en feront l'acquisition.
Ainsi, le principal avantage que nous obtenons en héritant des classes existantes ou en concevant un mécanisme d'héritage est la réutilisabilité du code.
Lectures complémentaires = >> Tutoriel sur l'héritage Java
Le format général pour hériter d'une classe est:
class derived_classname: access_specifier base_classname { };
Ici ' nom_classe_dérivée 'Est le nom de la classe dérivée,' access_specifier 'Est le mode d'accès, c'est-à-dire public, protégé ou privé dans lequel la classe dérivée doit hériter de la classe de base et' nom_classe_dérivée »Est le nom de la classe de base dont hérite la classe dérivée.
Modes d'héritage
Le «access_specifier» indiqué dans la déclaration d'héritage ci-dessus peut avoir ses valeurs comme indiqué ci-dessous.
En fonction du access_specifier spécifié lorsque nous héritons de la classe, nous avons différents modes d'héritage comme indiqué ci-dessous.
Héritage public
Syntaxe générale
class sub_class : public parent_class
Lorsque le spécificateur d'accès public est spécifié, les membres publics de la classe de base sont hérités en tant que public tandis que les membres protégés sont protégés. Les membres privés restent privés. C'est le mode d'héritage le plus populaire.
Héritage privé
Syntaxe générale
class sub_class : parent_class
L'héritage privé n'hérite de rien. Lorsque le spécificateur d'accès privé est utilisé, les membres publics et protégés de la classe de base deviennent également privés.
Héritage protégé
Syntaxe générale
class sub_class:protected parent_class
Lorsque le spécificateur d'accès protégé est utilisé, les membres publics et protégés de la classe de base deviennent des membres protégés dans la classe dérivée.
Notez que lorsque nous utilisons un spécificateur d'accès privé pour la classe de base, aucun des membres de la classe de base n'est hérité. Ils deviennent tous privés dans la classe dérivée.
Vous trouverez ci-dessous la représentation tabulaire de tous les modes d'accès et leur interprétation pour l'héritage.
Classe dérivée -> Classe de base | Privé | Publique | Protégé |
---|---|---|---|
Privé | Non hérité | Non hérité | Non hérité |
Publique | Privé | Publique | Protégé |
Protégé | Privé | Protégé | Protégé |
Ordre des constructeurs / destructeurs en héritage
Lorsque les classes sont héritées, les constructeurs sont appelés dans le même ordre que les classes sont héritées. Si nous avons une classe de base et une classe dérivée qui hérite de cette classe de base, alors le constructeur de classe de base (qu'il soit par défaut ou paramétré) sera appelé en premier, suivi du constructeur de classe dérivée.
Le programme suivant montre l'ordre des constructeurs dans l'héritage. Nous avons une classe de base «Base» qui a un constructeur par défaut et un constructeur paramétré. Nous dérivons une classe de ce qu'on appelle «Derived» qui a également un constructeur par défaut et un autre paramétré.
La sortie de ce programme montre l'ordre dans lequel les constructeurs sont appelés.
#include using namespace std; //order of execution of constructors in inheritance class Base { int x; public: // default constructor Base() { cout Production:
Constructeur par défaut de la classe de base
Constructeur par défaut de la classe de base
Constructeur par défaut de classe dérivée
Constructeur paramétré de classe de base
Constructeur paramétré par classe dérivée
Nous voyons qu'après avoir créé l'objet de classe de base, nous créons un objet de classe dérivé avec un constructeur par défaut. Lorsque cet objet est créé, le constructeur par défaut de la classe de base est d'abord appelé, puis le constructeur de la classe dérivée est exécuté.
De même, lorsque l'objet de classe dérivée est créé à l'aide du constructeur paramétré, le constructeur paramétré de classe de base est appelé en premier, puis le constructeur de classe dérivée est appelé.
Notez que s'il n'y avait pas de constructeur paramétré dans la classe de base, alors le constructeur par défaut aurait été appelé même pour construire l'objet de classe dérivée paramétré.
Mais la question demeure de savoir pourquoi le constructeur de classe de base est appelé lors de la construction des objets de classe dérivés?
On sait qu'un constructeur est utilisé pour créer des objets de la classe et aussi pour initialiser les membres de la classe. Lorsque l'objet de classe dérivée est créé, son constructeur n'a le contrôle que sur les membres de la classe dérivés.
Cependant, la classe dérivée hérite également des membres de la classe de base. Si seul le constructeur de classe dérivée était appelé, les membres de la classe de base hérités par la classe dérivée ne seraient pas initialisés correctement.
En conséquence, l'objet entier ne sera pas créé efficacement. C'est la raison pour laquelle tous les constructeurs de classe de base sont appelés en premier lorsqu'un objet de classe dérivé est créé.
Types d'héritage
Selon la manière dont la classe est dérivée ou le nombre de classes de base dont une classe hérite, nous avons les types d'héritage suivants, comme illustré dans la figure ci-dessous.

Nous explorerons chacun de ces types dans notre prochain tutoriel sur les «Types d'héritage».
Héritage de modèle
Lorsque notre implémentation implique des modèles, nous devons hériter ou dériver de classes de modèles, et nous utilisons l'héritage de modèles là-bas.
Passons directement à un exemple de programmation pour mieux comprendre l'héritage à l'aide de modèles.
#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< Production:
test de services Web questions et réponses d'entrevue
basecls_Template obj = 100
dérivécls_Child obj1 (hérité de basecls_Template = A
Dans le programme ci-dessus, nous avons un modèle nommé basecls_Template qui définit le modèle de classe pour la classe de base. Ensuite, nous définissons une classe dérivéecls_Child que nous voulons dériver d'une classe modèle.
Mais notez que la classe basecls_Template n'est qu'un type et non une classe. Par conséquent, nous ne pouvons pas dériver la classe dérivéecls_Child de ce modèle.
Par conséquent, si nous déclarons la classe enfant comme:
class derivedcls_Child : public basecls_Template
Cela entraînera une erreur. La raison étant basecls_Template est un type de données et non une classe. Ainsi, pour hériter des membres de basecls_Template, nous devons d'abord l'instancier avant d'en dériver.
Par conséquent, la déclaration ci-dessus, Classe dérivéecls_Child: public basecls_Template fonctionne très bien.
Dans cette instruction, nous avons instancié le modèle basecls_Template vers un modèle de classe de caractères. Une fois que nous utilisons cette classe de modèle instanciée, les autres éléments suivants, comme la création et l'utilisation d'objets, coïncident avec le fonctionnement habituel de l'héritage.
Composition
Jusqu'à présent, nous avons tout vu sur les relations d'héritage. L'héritage représente essentiellement le type de relations dans lesquelles la relation indique une partie. Par exemple, un serpent est une sorte de reptile. Nous pouvons également dire que le reptile fait partie de la classe animale.
En conclusion, l'héritage indique 'EST UN' type de relations dans lesquelles nous pouvons dire que la classe dérivée fait partie de la classe de base.
Nous pouvons également représenter les relations dans leur ensemble. Par exemple, si nous disons que la classe de salaire fait partie de la classe d'employé, alors nous ne la représentons pas correctement. Nous savons que les employés ont un salaire. Il est donc plus pratique de dire «l'employé a un salaire».
De même, si nous prenons la classe Véhicules comme exemple, nous pouvons dire que Véhicule a un moteur ou Véhicule a un châssis. Ainsi, toutes ces relations décrivent 'A UN' relations qui représentent un objet entier contenu dans une autre classe. Ceci est défini comme Composition .
Les relations représentées par la composition dépendent les unes des autres. Par exemple, un châssis ne peut exister sans véhicule. De même, le salaire ne peut exister sans un employé.
Nous pouvons représenter la composition schématiquement comme indiqué ci-dessous:

La composition est également appelée Confinement. Dans la représentation ci-dessus, nous avons montré une classe parente. Contrairement à l'héritage, nous incluons un objet de classe enfant dans la classe parente. C'est le confinement ou la composition.
techniques de test boîte noire avec exemples
Prenons un exemple de programmation pour comprendre cela.
#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< Production:
10001 Ved
A-101 Silver Springs Aundh Pune Maharashtra
Dans cet exemple, nous avons une classe parent Employee et une classe enfant Address. Dans la classe parente Employee, nous avons déclaré un pointeur vers la classe Address et initialisons également cet objet dans le constructeur Employee. Ainsi, nous décrivons la relation entre l'employé et une adresse qui est la composition.
Comment décider entre composition et héritage?
La composition et l'héritage décrivent tous deux les relations entre les classes. Alors que l'héritage décrit la relation «IS-A», la composition décrit la relation «HAS-A».
Maintenant, la question est la suivante: quand devrions-nous utiliser l'héritage et quand devrions-nous utiliser la composition? En fait, nous ne pouvons pas décider des situations exactes comme quand nous devrions utiliser l'une ou l'autre. C'est parce que chacun a ses propres avantages et inconvénients.
Les deux favorisent la réutilisabilité du code. L'héritage peut rendre le code volumineux à mesure que les solutions deviennent complexes, mais en même temps, il nous permet également d'étendre le code existant. Ainsi, nous devrions utiliser l'héritage lorsque notre exigence est de modifier et d'utiliser les propriétés et la méthode d'une autre classe à l'intérieur de la nouvelle classe.
En d'autres termes, lorsque nous voulons ajouter plus de propriétés et étendre la classe existante. Par contre, lorsque nous ne voulons pas modifier les propriétés et le comportement d'une autre classe, mais simplement l'utiliser à l'intérieur de la classe, nous optons pour la composition.
Ainsi, la meilleure décision est de savoir si utiliser la composition ou l'héritage sera prise en pesant les avantages et les inconvénients des deux techniques pour la situation particulière.
= >> Lire aussi Composition en Java
Conclusion
Ainsi, nous sommes arrivés à la fin de notre sujet sur l'héritage. Nous avons vu différents modes d'héritage. Nous avons également vu les types d'héritage, que nous explorerons dans notre prochain tutoriel. Nous avons appris l'ordre des constructeurs qui sont exécutés en cas d'héritage.
Nous avons également étudié les modèles et l'héritage. Nous devons instancier un modèle avant de pouvoir l'utiliser dans l'héritage car le modèle lui-même est un type de données et nous ne pouvons pas hériter d'un type de données.
La composition est un autre type de relation de classe et nous devons d'abord connaître la situation exacte et ensuite seulement nous pouvons décider d'utiliser la composition ou l'héritage.
Dans notre prochain tutoriel, nous en verrons plus sur les types d'héritage.
=> Regardez la série de formations C ++ simple ici.
lecture recommandée
- Types d'héritage en C ++
- Polymorphisme d'exécution en C ++
- Fonctions Friend en C ++
- Utilisation de la classe Selenium Select pour la gestion des éléments déroulants sur une page Web - Tutoriel Selenium # 13
- Classes et objets en C ++
- Statique en C ++
- Tutoriel Unix Pipes: Pipes dans la programmation Unix
- Tutoriel sur l'interface Java et la classe abstraite avec des exemples