C++ 抽象类:构造函数是还是不是?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19808667/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ Abstract Class: constructor yes or no?
提问by user2452426
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
):
如果类是抽象的,为什么我们有一个构造函数?它稍后使用这个类(Boss
是公共派生自Employee
):
void Boss::Boss (const char* first, const char* last, double s)
: Employee (first, last)
回答by JBL
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.
实际上,正如您的示例所示,抽象类可以具有私有成员,这些成员可以由此类的成员函数使用。并且这些成员必须被初始化。构造函数是一种方法(例如,在派生类中使用初始化列表,如您的第二个示例所示),在我看来比例如函数更好init()
。
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.
然后,这些成员变量初始化的责任可能属于抽象类(至少总是对于私有成员,因为派生类将无法初始化它们,但可以使用一些可能使用/依赖的继承成员函数在这些成员上)。因此,抽象类实现构造函数是完全合理的。
回答by odedsh
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++.
这些子类将在实例化时构造基类,它们将调用其超类的构造函数,这就是抽象类在 C++ 中具有构造函数的原因。
So you can't create an instance directly and call the constructor directly but future sub-classes will.
所以你不能直接创建一个实例并直接调用构造函数,但未来的子类会。
回答by Juraj Blaho
The Employee
class has data and this data needs to be initialized somehow. Constructor is a good way to do that.
这个Employee
类有数据,这个数据需要以某种方式初始化。构造函数是一个很好的方法来做到这一点。
回答by Gaurav K
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?
如果抽象基类没有构造函数,firstname , lastname
那么在创建派生类的对象时,如何为派生类的成员赋值?
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
.
假设有一个Manager Class
派生自Employee
它添加Salary
数据和实现earning()
。NowEmployee
是一个抽象类,但它Manager
是 a concrete class
,因此您可以拥有Manager
. 但是当您实例化 时Manager
,您需要初始化/分配值给从 继承的成员base class i.e. Employee
。一种方法是您可以setFirstName() & setLastName()
为此目的在基类中使用它们,并且您可以在构造函数中使用它们derived class i.e. Manager
或更方便的方法是在您的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;
}
回答by MaHuJa
firstNameand lastNameare private members, not accessible to Boss. All the interface to those has to be present in the Employee class, including initialization.
firstName和lastName是私有成员,Boss 无法访问。所有这些接口都必须存在于 Employee 类中,包括初始化。
回答by ldgorman
"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."
“一个抽象类至少包含一个纯虚函数。您可以通过在类声明中的虚成员函数声明中使用纯说明符 (= 0) 来声明一个纯虚函数。”
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)
first
并且last
在基类中定义,因此,为了初始化它们,我们需要调用基类的构造函数: Employee (first, last)
回答by Howdy
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.
抽象类的目的是您希望通过派生类扩展某些功能。它可以有构造函数吗?是的,它可以,目的是从基类初始化局部变量。您应该避免在 Abstract 中使用公共构造函数并仅使用 protected。
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" :).
你的例子不是一个好例子。不确定它是什么书,但那是坏例子。它就像定义带有变量名称“iAmString”的 int 变量 :)。
int iAmString = 12;
int iAmString = 12;
Cheers
干杯
回答by CITBL
To initialize firstName and lastName. Otherwise you will have to write a code to initilze them in each derived classes' constructors
初始化 firstName 和 lastName。否则,您将不得不编写代码在每个派生类的构造函数中初始化它们