web-dev-qa-db-fra.com

Classe abstraite C ++: constructeur oui ou non?

Une classe avec une (ou plusieurs) fonctions pures virtuelles virtuelles est abstraite et ne peut pas être utilisée pour créer un nouvel objet. Elle n'a donc pas de constructeur.

Je lis un livre qui fournit l'exemple suivant:

class Employee {
   public:
       Employee(const char*, const char*);
       ~Employee();
       const char* getFirstName() const;
       const char* getLastName() const;


       virtual double earnings() const=0  // pure virtual => abstract class
       virtual void print() const

  private:
       char* firstName, lastName;
};

Si la classe est abstraite, pourquoi avons-nous un constructeur? Il utilisera cette classe plus tard (Boss est un public dérivé de Employee):

void Boss::Boss (const char* first, const char* last, double s)
     : Employee (first, last)
53
user2452426

Vous avez raison de dire qu'une classe qui a une fonction virtuelle pure est abstraite et ne peut pas être instanciée. Mais vous avez tort quand vous dites qu'il ne peut pas y avoir de constructeur.

En effet, comme le montre l'exemple de votre exemple, une classe abstraite peut avoir des membres privés pouvant être utilisés par les fonctions membres de cette classe. Et ces membres doivent être initialisés. Un constructeur est un moyen de le faire (par exemple avec une liste d’initialisation dans la classe dérivée, comme le montre votre deuxième exemple), mieux à mon avis qu’une fonction init() par exemple.

Édition de mon commentaire dans la réponse: Une classe abstraite peut avoir des variables membres et des fonctions membres potentiellement non virtuelles, de sorte que chaque classe dérivée de la première implémente des fonctionnalités spécifiques.

Ensuite, la responsabilité de l'initialisation de ces variables membres peut appartenir à la classe abstraite ( au moins toujours pour les membres privés , car la classe dérivée ne être capable de les initialiser, mais pourrait utiliser certaines fonctions membres héritées pouvant utiliser/compter sur ces membres). Ainsi, il est parfaitement raisonnable que les classes abstraites implémentent des constructeurs.

69
JBL

Une classe avec une fonction virtuelle pure ne peut pas être instanciée. On s'attend à ce qu'il ait des sous-classes qui l'étendront et fourniront la fonctionnalité manquante.

Ces sous-classes construiront la classe de base quand elles seront instanciées, elles appelleront le constructeur de leur super classe, raison pour laquelle les classes abstraites ont des constructeurs en c ++.

Vous ne pouvez donc pas créer directement d'instance et appeler directement le constructeur, mais les futures sous-classes le feront.

21
odedsh

La classe Employee a des données et ces données doivent être initialisées d'une manière ou d'une autre. Constructeur est un bon moyen de le faire.

4
Juraj Blaho

Si la classe abstraite de base n'a pas de constructeur, comment affecteriez-vous des valeurs aux membres firstname , lastname Pour toute classe dérivée, lorsque vous créez un objet de la classe dérivée?

Supposons qu'il existe un Manager Class Dérivé de Employee qui ajoute des données Salary et implémente earning(). Maintenant, Employee est une classe abstraite mais Manager est un concrete class Et vous pouvez donc avoir un objet de Manager. Mais lorsque vous instancialisez Manager, vous devez initialiser/affecter des valeurs aux membres hérités de base class i.e. Employee. Une façon est que vous pouvez avoir setFirstName() & setLastName() dans la classe de base à cette fin et vous pouvez les utiliser dans le constructeur pour derived class i.e. Manager Ou une méthode plus pratique serait d'avoir un constructeur dans votre base abstract class Employee.

Voir le code ci-dessous:

#include <iostream>
#include <cstring>
#include <cstdlib>

using namespace std;


class Employee {
   public:
       Employee(const char*, const char*);
       ~Employee();
       const char* getFirstName() const;
       const char* getLastName() const;


       virtual double earnings() const=0;  // pure virtual => abstract class
       virtual void print() const;

  private:
       char* firstname;
       char* lastname;
};

Employee::Employee(const char* first, const char* last){
firstname= (char*) malloc((strlen(first)+1)*sizeof(char));
lastname= (char*) malloc((strlen(last)+1)*sizeof(char));
strcpy(firstname,first);
strcpy(lastname,last);
}

Employee::~Employee(){
free(firstname);
free(lastname);
cout << "Employee destructed" << endl;
}

const char* Employee::getFirstName() const{ return firstname;}
const char* Employee::getLastName() const{ return lastname; }
void Employee::print() const{
      cout << "Name: " << getFirstName() << " " << getLastName() << endl;
      }



class Manager:public Employee{
   public:
      Manager(char* firstname,char* lastname,double salary):
    Employee(firstname,lastname),salary(salary){}

      ~Manager(){}

      double earnings() const {return salary;}

   private:
      double salary;          
};

int main(){

Manager Object("Andrew","Thomas",23000);    
Object.print();
cout << " has Salary : " << Object.earnings() << endl;

    return 0;
}
3
Gaurav K

"Une classe abstraite contient au moins une fonction virtuelle pure. Vous déclarez une fonction virtuelle pure en utilisant un spécificateur pur (= 0) dans la déclaration d'une fonction membre virtuelle dans la déclaration de classe."

en ce qui concerne:

void Boss::Boss (const char* first, const char* last, double s)
     : Employee (first, last)

first et last sont définis dans la classe de base. Par conséquent, pour les initialiser, nous devons appeler le constructeur de la classe de base : Employee (first, last).

0
ldgorman

firstName et lastName sont des membres privés, non accessibles à Boss. Toutes les interfaces avec celles-ci doivent être présentes dans la classe Employee, y compris l’initialisation.

0
MaHuJa