C++ Classe abstraite: constructeur oui ou non?

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

je suis en train de lire un livre qui donne 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 nous avons un constructeur? Il utilise cette classe plus tard (Boss public est dérivé de Employee):

void Boss::Boss (const char* first, const char* last, double s)
     : Employee (first, last)
40
demandé sur ネロク 2013-11-06 13:46:53

8 réponses

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

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

Modifier mon commentaire dans la réponse: une classe abstraite peut avoir des variables membres et potentiellement des fonctions membres 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 peuvent appartenir à la classe abstraite (au moins, toujours privé pour les membres, parce que la classe dérivée ne être en mesure de les initialiser, mais pourrait utiliser certaines fonctions membres héritées qui peuvent utiliser/compter sur ces membres). Ainsi, il est parfaitement raisonnable pour des classes abstraites de mettre en œuvre des constructeurs.

58
répondu JBL 2017-04-05 09:08:52

une classe avec une fonction purement virtuelle ne peut pas être instanciée. On s'attend à ce qu'il comporte des sous-classes qui l'étendront et fourniront les fonctionnalités manquantes.

ces sous-classes construiront la classe de base quand elles seront instanciées, elles appelleront le constructeur de leur super classe, c'est pourquoi les classes abstraites ont des constructeurs en c++.

donc vous ne pouvez pas créer une instance directement et appeler le constructeur directement mais les sous-classes futures le feront.

17
répondu odedsh 2013-11-06 09:55:48

Employee classe a données et ces données doit être initialisé en quelque sorte. Le constructeur est un bon moyen de le faire.

4
répondu Juraj Blaho 2013-11-06 09:49:15

si la classe abstract de base n'a pas de constructeur, comment assigneriez-vous des valeurs à firstname , lastname membres pour toute classe dérivée, lorsque vous créez un objet de la classe dérivée?

supposons qu'il y ait un Manager Class dérivé de Employee ajoute Salary données et met en œuvre earning(). Maintenant Employee est une classe abstraite mais Manager est un concrete class et donc vous pouvez avoir un objet de Manager. Mais quand vous êtes instantialting Manager, vous devez initialiser/assigner des valeurs pour les membres hérités d' base class i.e. Employee. Une façon est que vous pouvez avoir setFirstName() & setLastName() dans la classe de base à cet effet et vous pouvez les utiliser dans le constructeur derived class i.e. Manager ou de façon 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;
}
2
répondu Gaurav K 2014-05-08 02:42:42

prénom et nom sont des membres privés, non accessibles au patron. Toutes les interfaces avec ceux - ci doivent être présentes dans la classe des employés, y compris l'initialisation.

0
répondu MaHuJa 2013-11-06 09:50:47

"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 de membre virtuel dans la déclaration de classe."

sujet:

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

first et last sont définies dans la classe de base, par conséquent, afin de les initialiser, nous avons besoin de faire un appel au constructeur de la classe de base : Employee (first, last)

0
répondu ldgorman 2013-11-06 09:55:36

Pour initialiser firstName et lastName. Sinon, vous devrez écrire un code pour les initialiser dans les constructeurs de chaque classe dérivée

-1
répondu CITBL 2013-11-06 09:51:09

le but de la classe abstraite est que vous voulez étendre certaines fonctionnalités par des classes dérivées. Peut-il y avoir de constructeur? Oui, il peut et le but est d'initialiser les variables locales de la classe de base. Vous devez éviter D'utiliser le constructeur public dans L'abstrait et utiliser protégé seulement.

L'exemple que vous avez n'est pas un bon exemple. Je ne sais pas quel livre il est, mais que le mauvais exemple. C'est comme définir une variable int avec le nom de la variable "iAmString" :).

int iAmString = 12;

Cheers

-1
répondu Howdy 2014-02-28 20:48:38