C ++抽象类:构造函数是或否?

时间:2013-11-06 09:46:54

标签: c++ class constructor abstract

具有一个(或多个)虚拟纯函数的类是抽象的,它不能用于创建新对象,因此它没有构造函数。

我正在读一本提供以下示例的书:

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

如果类是抽象的,为什么我们有一个构造函数?它稍后使用此类(Boss是公共派生自Employee):

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

9 个答案:

答案 0 :(得分:66)

当你说具有纯虚函数的类是抽象的并且无法实例化时,你就更正了。但是当你说它不具备构造函数时,你就错了。

实际上,正如您的示例所示,抽象类可以拥有私有成员,可以由此类的成员函数使用。这些成员必须初始化。构造函数是一种方法(例如,在派生类中使用初始化列表,如第二个示例所示),在我看来比例如init()函数更好。

在答案中编辑我的评论:抽象类可以包含成员变量和潜在的非虚拟成员函数,因此前者的每个派生类都实现特定的功能。

然后,初始化这些成员变量的责任可能属于抽象类(至少总是属于私有成员,因为派生类不能初始化它们,但是可以使用一些可能使用/依赖这些成员的继承成员函数。因此,它使抽象类实现构造函数完全合理。

答案 1 :(得分:21)

无法实例化具有纯虚函数的类。它应该有子类,它将扩展它并提供缺少的功能。

这些子类在实例化时将构造基类,它们将调用其超类的构造函数,这就是抽象类在c ++中具有构造函数的原因。

因此,您无法直接创建实例并直接调用构造函数,但未来的子类将会。

答案 2 :(得分:4)

Employee类有数据,需要以某种方式初始化此数据。构造函数是一种很好的方法。

答案 3 :(得分:3)

如果基本抽象类没有构造函数,那么在创建派生类的对象时,如何为任何派生类的firstname , lastname成员赋值?

假设有一个Manager Class派生自Employee,其中添加Salary数据并实现earning()。现在Employee是一个抽象类,但Managerconcrete class,因此您可以拥有Manager的对象。但是当您实例化Manager时,您需要为从base class i.e. Employee继承的成员初始化/分配值。一种方法是,为此目的,您可以在基类中使用setFirstName() & setLastName(),并且可以在derived class i.e. Manager的构造函数中使用它们,或者更方便的方法是在base abstract class Employee中使用构造函数

请参阅以下代码:

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

答案 4 :(得分:0)

firstName lastName 是私有成员,Boss无法访问。所有接口都必须出现在Employee类中,包括初始化。

答案 5 :(得分:0)

“抽象类包含至少一个纯虚函数。通过在类声明中的虚拟成员函数声明中使用纯说明符(= 0)来声明纯虚函数。”

关于:

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

firstlast在基类中定义,因此,为了初始化它们,我们需要调用基类: Employee (first, last)

答案 6 :(得分:0)

抽象类是其中至少包含一个纯虚函数的类。我们不能实例化一个抽象类。但它可以有构造函数。请参阅下面的示例。如果我们不重写派生类中的虚函数,它也会变成一个抽象类,

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

答案 7 :(得分:-1)

初始化firstName和lastName。否则,您将不得不编写一个代码来在每个派生类的构造函数

中初始化它们

答案 8 :(得分:-1)

Abstract类的目的是您希望通过派生类扩展某些功能。它有构造函数吗?是的它可以,目的是从基类初始化局部变量。您应该避免在Abstract中使用公共构造函数并仅使用protected。

你所拥有的例子不是一个好例子。不知道它是什么书,但不好的例子。它就像使用变量“iAmString”的名称定义int变量:)。

int iAmString = 12;

干杯