89

A class with one (or more) virtual pure functions is abstract, and it can't be used to create a new object, so it doesn't have a constructor.

I'm reading a book that provides the following example:

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;
};

If the class is abstract why we have a constructor? It uses this class later (Boss is public derived from Employee):

void Boss::Boss (const char* first, const char* last, double s)
     : Employee (first, last)
JFMR
  • 23,265
  • 4
  • 52
  • 76
user2452426
  • 991
  • 1
  • 7
  • 7
  • 1
    I think this will help: http://stackoverflow.com/questions/9399290/why-does-a-purely-virtual-abstract-class-require-a-constructor-in-particular-fo – Abhishek Bansal Nov 06 '13 at 09:50

9 Answers9

96

You're correct when you say that a class that has a pure virtual function is abstract and can't be instantiated. But you're wrong when you say that it can't have a constructor.

Indeed, as your example show, an abstract class can have private members, that may be used by member functions of this class. And these members must be initialized. A constructor is a way to do that (e.g. with an initialization list in the derived class, as your second sample shows), better in my opinion than an init() function for example.

Editing my comment in the answer: An abstract class can have member variables and potentially non-virtual member functions, so that every derived class from the former implements specific features.

Then, the responsibility for the initialization of these members variables may belong to the abstract class (at least always for private members, because the derived class wouldn't be able to initialize them, yet could use some inherited member functions that may use/rely on these members). Thus, it makes it perfectly reasonable for abstract classes to implement constructors.

JBL
  • 12,588
  • 4
  • 53
  • 84
  • Thank you everybody. So an abstract class can't be instatiated but it can have a constructor...ok...now clear to me. But was wondering why in the above example the data members of base class (firstName and lastName) are specified as private and not protected. In order to keep the encapsulation? Thanks again – user2452426 Nov 06 '13 at 10:47
  • 3
    Yes ! As you've seen, abstract classes can still have members and/or non pure virtual member functions (for example, to ensure that every derived provides a specific feature). That doesn't mean the derived classes (or people manipulating a pointer to an instance of the abstract class in case of polymorphism) should know about the implementation details of the feature. – JBL Nov 06 '13 at 11:08
35

A class with a pure virtual function can't be instantiated. It is expected to have sub-classes that will extend it and provide the missing functionality.

These sub-classes will construct the base class when they are instantiated, they will call the constructor of their super class which is why abstract classes have constructors in c++.

So you can't create an instance directly and call the constructor directly but future sub-classes will.

odedsh
  • 2,594
  • 17
  • 17
8

The Employee class has data and this data needs to be initialized somehow. Constructor is a good way to do that.

Juraj Blaho
  • 13,301
  • 7
  • 50
  • 96
  • 1
    Can I suggest that you explain how/in what circumstance the constructor would be called? I think that is what is confusing the question asker. – Azendale May 25 '14 at 00:23
  • @Azendale You would call it in the constructor of the derived concrete class through an initialization list. MyClass(const char *firstName, const char *lastName) : Employee(firstName, lastName) {} – Scooter Jul 02 '15 at 05:37
6

If The base abstract class does not have a constructor, how would you assign values to firstname , lastname members for any derived class, when you are creating an object of the derived class?

Suppose there is a Manager Class derived from Employee which adds Salary data and implements earning(). Now Employee is an abstract class but Manager is a concrete class and hence you can have an object of Manager. But when you are instantialting Manager, you need to initialize/assign values to members inherited from base class i.e. Employee. One way is that you can have setFirstName() & setLastName() in the base class for this purpose and you can use them in the constructor for derived class i.e. Manager or more convenient way would be to have a constructor in your base abstract class Employee.

See the code below:

#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;
}
Gaurav K
  • 2,864
  • 9
  • 39
  • 68
2

An Abstract class is a class which have at least one pure virtual function in it. We cannot instantiate an abstract class. But it can have constructors. see the below example. If we not override the virtual function in derived class, it also become an abstract class,

class Abstract {
private:
    int x, y;
public:
    virtual void a() = 0;//pure virtual function
    Abstract(int x1, int y1) {
        x = x1;
        y = y1;
    }
};

class Base :public Abstract {
private:
    int z;
public:
    Base(int x, int y, int z1) :Abstract(x, y) {
        z = z1;
    }
    void a() {
 }
};

int main() {
    Base b(1, 2, 3);
}
1

"An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration."

regarding:

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

first and last are defined in the base class, therefore, in order to initialize them, we need to make a call to the constructor of the base class : Employee (first, last)

ldgorman
  • 1,553
  • 1
  • 14
  • 39
  • [IBM Abstract classes (C++ only)](http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr142.htm) – ldgorman Nov 06 '13 at 09:57
0

firstName and lastName are private members, not accessible to Boss. All the interface to those has to be present in the Employee class, including initialization.

MaHuJa
  • 3,148
  • 1
  • 18
  • 6
0

The purpose of Abstract class is that you want to extend some functionality by derived classes. Can it have constructor? Yes it can and the purpose is to initialize local variables from the base class. You should avoid using public constructor in Abstract and use protected only.

The example you have is not a good example. Not sure what book it is but that the bad example. Its like defining int variable with name of variable "iAmString" :).

int iAmString = 12;

Cheers

Howdy
  • 11
  • "You should avoid using public constructor in Abstract and use protected only. " why? There is no danger of accidentely calling the constructor outside of a derived class, it will lead to a compiler error. "You should.." without giving a reason is not good imho – 463035818_is_not_an_ai Aug 07 '18 at 15:26
-1

To initialize firstName and lastName. Otherwise you will have to write a code to initilze them in each derived classes' constructors

CITBL
  • 1,587
  • 3
  • 21
  • 36