C++ 抽象类:构造函数是或否?
Posted
技术标签:
【中文标题】C++ 抽象类:构造函数是或否?【英文标题】:C++ Abstract Class: constructor yes or no? 【发布时间】:2013-11-17 11:43:30 【问题描述】:具有一个(或多个)虚纯函数的类是抽象的,不能用于创建新对象,因此它没有构造函数。
我正在阅读一本提供以下示例的书:
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)
【问题讨论】:
你的第一句话不正确,被代码示例否定了。你到底在问什么? 我认为这会有所帮助:***.com/questions/9399290/… 【参考方案1】:Employee
类有数据,这些数据需要以某种方式初始化。构造函数是一个很好的方法。
【讨论】:
我能否建议您解释一下如何/在什么情况下调用构造函数?我认为这让提问者感到困惑。 @Azendale 您可以通过初始化列表在派生具体类的构造函数中调用它。 MyClass(const char *firstName, const char *lastName) : Employee(firstName, lastName) 【参考方案2】:firstName 和 lastName 是私有成员,Boss 无法访问。所有这些的接口都必须存在于 Employee 类中,包括初始化。
【讨论】:
【参考方案3】:初始化 firstName 和 lastName。否则你将不得不编写代码在每个派生类的构造函数中初始化它们
【讨论】:
【参考方案4】:当您说具有纯虚函数的类是抽象的并且不能被实例化时,您是对的。但是当你说它不能有构造函数时你就错了。
确实,如您的示例所示,抽象类可以具有私有成员,此类的成员函数可以使用这些成员。并且这些成员必须被初始化。构造函数是一种方法(例如,在派生类中使用初始化列表,如您的第二个示例所示),在我看来比 init()
函数更好。
在答案中编辑我的评论:抽象类可以具有成员变量和潜在的非虚拟成员函数,因此从前者派生的每个派生类都实现特定功能。
那么,初始化这些成员变量的责任可能属于抽象类(至少总是私有成员,因为派生类不能初始化它们,但可以使用一些可能使用/依赖这些成员的继承成员函数)。因此,抽象类实现构造函数是完全合理的。
【讨论】:
谢谢大家。所以一个抽象类不能被实例化,但它可以有一个构造函数......好吧......现在我清楚了。但是想知道为什么在上面的例子中基类的数据成员(名字和姓氏)被指定为私有而不是受保护的。为了保持封装?再次感谢 是的!如您所见,抽象类仍然可以具有成员和/或非纯虚成员函数(例如,以确保每个派生类都提供特定功能)。这并不意味着派生类(或在多态的情况下操作指向抽象类实例的指针)应该知道该特性的实现细节。【参考方案5】:“一个抽象类至少包含一个纯虚函数。您可以通过在类声明中的虚成员函数声明中使用纯说明符 (= 0) 来声明纯虚函数。”
关于:
void Boss::Boss (const char* first, const char* last, double s)
: Employee (first, last)
first
和last
是在基类中定义的,因此,为了初始化它们,我们需要调用基类: Employee (first, last)
的构造函数
【讨论】:
IBM Abstract classes (C++ only)【参考方案6】:不能实例化具有纯虚函数的类。预计会有子类来扩展它并提供缺失的功能。
这些子类在实例化时会构造基类,它们会调用超类的构造函数,这就是为什么抽象类在 c++ 中有构造函数。
所以你不能直接创建实例并直接调用构造函数,但未来的子类会。
【讨论】:
【参考方案7】:抽象类的目的是你想通过派生类扩展一些功能。它可以有构造函数吗?是的,它可以,目的是从基类初始化局部变量。您应该避免在 Abstract 中使用公共构造函数并仅使用 protected。
你的例子不是一个好例子。不知道它是什么书,但那是个坏例子。就像用变量“iAmString”的名称定义int变量:)。
int iAmString = 12;
干杯
【讨论】:
"你应该避免在 Abstract 中使用公共构造函数,而只使用 protected。" 为什么?在派生类之外意外调用构造函数是没有危险的,它会导致编译器错误。 “你应该..”没有给出理由是不好的恕我直言【参考方案8】:如果基础抽象类没有构造函数,当您创建派生类的对象时,如何将值分配给任何派生类的firstname , lastname
成员?
假设有一个从Employee
派生的Manager Class
,它添加了Salary
数据并实现了earning()
。现在Employee
是一个抽象类,但Manager
是concrete 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;
【讨论】:
【参考方案9】:抽象类是其中至少有一个纯虚函数的类。我们不能实例化一个抽象类。但它可以有构造函数。请参见下面的示例。如果不重写派生类中的虚函数,它也会变成抽象类,
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);
【讨论】:
以上是关于C++ 抽象类:构造函数是或否?的主要内容,如果未能解决你的问题,请参考以下文章