Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/reporting-services/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;抽象类:构造函数是还是否?_C++_Class_Constructor_Abstract - Fatal编程技术网

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

C++ C++;抽象类:构造函数是还是否?,c++,class,constructor,abstract,C++,Class,Constructor,Abstract,具有一个(或多个)虚拟纯函数的类是抽象的,不能用于创建新对象,因此它没有构造函数 我正在读一本书,书中提供了以下示例: class Employee { public: Employee(const char*, const char*); ~Employee(); const char* getFirstName() const; const char* getLastName() const; virtual d

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

我正在读一本书,书中提供了以下示例:

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
派生的公共类):


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

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

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

如果您说一个具有纯虚函数的类是抽象的,并且不能实例化,那么您是正确的。但当你说它不能有构造函数时,你错了

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

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

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

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

关于:

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

first
last
是在基类中定义的,因此,为了初始化它们,我们需要调用基类的构造函数
:Employee(first,last)
不能实例化具有纯虚函数的类。它应该有子类来扩展它并提供缺少的功能

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


因此,您不能直接创建实例并直接调用构造函数,但将来的子类会这样做。

抽象类的目的是希望通过派生类扩展某些功能。它能有构造器吗?是的,它可以,目的是从基类初始化局部变量。您应该避免抽象地使用公共构造函数,而只使用受保护的构造函数

你的例子不是一个好例子。我不确定这是哪本书,但那是个坏例子。这类似于定义名为“iAmString”的int变量(如有)

int iAmString=12


欢呼

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

假设有一个从
Employee
派生的
Manager类,它添加
Salary
数据并实现
earning()
。现在
Employee
是一个抽象类,而
Manager
是一个
具体类
,因此您可以拥有
Manager
的对象。但是,当实例化
管理器时,需要初始化/分配从
基类继承的成员的值,即Employee
。一种方法是,可以在基类中使用
setFirstName()&setLastName()
,并且可以在
派生类的构造函数中使用它们,即Manager
,或者更方便的方法是在
基本抽象类中使用构造函数

请参阅下面的代码:

#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;
}
#包括
#包括
#包括
使用名称空间std;
班级员工{
公众:
雇员(常数字符*,常数字符*);
~Employee();
常量char*getFirstName()常量;
常量char*getLastName()常量;
virtual double earning()const=0;//纯虚拟=>抽象类
虚空打印()常量;
私人:
char*名字;
char*lastname;
};
Employee::Employee(常量字符*第一个,常量字符*最后一个){
firstname=(char*)malloc((strlen(first)+1)*sizeof(char));
lastname=(char*)malloc((strlen(last)+1)*sizeof(char));
strcpy(firstname,first);
strcpy(lastname,last);
}
雇员::~Employee(){
免费(名字);
免费(姓氏);

难道你的第一句话不正确并且被代码示例否定了吗?你到底在问什么?我想这会有帮助:谢谢大家。所以抽象类不能被安装,但它可以有一个构造函数…好吧…现在我明白了。但是我想知道为什么在上面的示例中基类(firstName和lastName)的数据成员被指定为私有且不受保护。为了保持封装?再次感谢是!正如您所看到的,抽象类仍然可以有成员和/或非纯虚拟成员函数(例如,确保每个派生类都提供特定功能)。这并不意味着派生类(或者在多态情况下操纵抽象类实例指针的人)应该知道该特性的实现细节。我建议您解释一下构造函数是如何/在什么情况下运行的
#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;
}