我正在看我书中的以下代码:
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long getArea() = 0; // Pure virtual function
virtual long getPerim() = 0;
virtual void draw() = 0;
};
现在它说这些虚函数使类抽象(我从Java中理解),因此无法实例化类。
但是,它说:“通过在类声明中包含一个或多个虚函数,类是抽象数据类型。”
这是否意味着我宣布一个具有 ONE 纯虚函数的类:
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long getArea() = 0; // Only pure virtual function
virtual long getPerim(){}
virtual void draw(){}
};
整个班级变得抽象吗?因为如果一个类有100多个方法,那么如果我决定稍后将它变成抽象的话,为每个方法编写=0
将会很繁琐。
答案 0 :(得分:12)
是的,单个纯virtual
方法足以使类抽象化。
此外,如果没有其他方法适合纯粹,你总是可以使析构函数为纯virtual
。
另外,你的析构函数可能应该是virtual
,因为你显然要继承这个类。如果您计划通过指向基类型的指针删除派生类型的对象,则必须执行此操作。
答案 1 :(得分:2)
你是正确的,因为一个纯虚方法足以使类抽象化。这意味着您必须在派生类中实现该方法以实例化(派生类的实例)。
我的“100多种方法课程”存在问题。通常这是设计非常糟糕的迹象。
我也有一些问题,你的“每种方法写作= 0很乏味”的态度。首先,我不明白为什么编写= 0比编写{}作为默认的无操作实现更为繁琐(如果方法返回任何内容,如getPerim()
那样,那么您将面临未定义的行为风险没有回复的东西)。但主要是,业务逻辑决定是否存在默认行为,而不是写作的努力。
记住Liskov替换原则:虽然你不能拥有你的基类的实例,但是有人会有一个指针或对它的引用,并且在其上调用虚方法而不必知道它们真正具有哪个类。 (顺便提一下,利斯科夫是女性,名字芭芭拉,并在1983年左右的某个时候说过这个原则。)
顺便说一句,你的抽象基类几乎肯定会有一个虚拟析构函数。
不会改变类状态的方法应该声明为const。
答案 2 :(得分:1)
将函数标记为纯不仅使类成为抽象,它使任何不覆盖函数的派生类也都是抽象的。
因此,如果要强制派生类实现所有这些函数,那么将它们全部变为纯粹。如果派生类只实现getArea
而不实现其他两个是有意义的,那么只标记getArea
纯。在这个例子中,我怀疑它没有有意义,因为如果所有派生类都添加了计算区域的方法,那么基类仍然无法计算周长。 / p>
答案 3 :(得分:0)
将方法声明为纯虚方法意味着继承您的类的类必须实现该方法或将其保留为纯虚拟,在这种情况下,派生类也将是一个无法实例化的抽象类。
另外,正如Luchian先前所说,你应该总是将析构函数声明为每个将被继承的类的虚拟。