7

我正在看我书中的以下代码:

class Shape
{
    public:
        Shape(){}
        ~Shape(){}
        virtual long getArea() = 0; // Pure virtual function
        virtual long getPerim() = 0;
        virtual void draw() = 0;
};

现在它说这些虚函数使类抽象(我从Java中理解),因此无法实例化该类。

但是,它说: “通过在类声明中包含一个或多个虚函数,类是抽象数据类型。”

这是否意味着如果我用一个纯虚函数声明一个

class Shape
{
    public:
        Shape(){}
        ~Shape(){}
        virtual long getArea() = 0; // Only pure virtual function
        virtual long getPerim(){}
        virtual void draw(){}
};

整个班级都变得抽象了吗?=0因为如果一个类有 100 多个方法,如果我决定稍后将其抽象化,那么为每个方法编写都会很乏味。

4

4 回答 4

12

是的,一个纯virtual方法就足以使类抽象。

virtual此外,如果没有其他方法适合纯析构函数,则始终可以使析构函数纯。

此外,你的析构函数应该是virtual,因为你显然要从这个类继承。如果您计划通过指向基类型的指针删除派生类型的对象,则这是强制性的。

于 2012-10-23T13:34:05.253 回答
2

您是正确的,因为一个纯虚拟方法足以使类抽象。这意味着您必须在派生类中实现该方法才能实例化(派生类的)实例。

我对您的“具有 100 多种方法的课程”有疑问。通常这是设计非常糟糕的标志。

我也对您“为每种方法都写 = 0”的态度感到厌烦。首先,我不明白为什么写 =0 比写 {} 作为默认的无操作实现更乏味(如果该方法返回任何东西,就像这样getPerim()做,你会因为不返回某些东西而冒着未定义的行为的风险)。不过,首先,业务逻辑决定了是否存在默认行为,而不是编写工作量。

记住 Liskov 替换原则:虽然一个人不能拥有基类的实例,但有人会拥有一个指针或引用,并在其上调用虚方法,而不必知道他们真正拥有的是什么类。(顺便说一下,Liskov 是女性,名字叫 Barbara,并在 1983 年左右的某个时候陈述了这一原则)。

顺便说一句,您的抽象基类几乎肯定应该有一个虚拟析构函数。

不会改变类状态的方法应该声明为 const。

于 2012-10-23T13:44:20.920 回答
1

将函数标记为纯不仅使类抽象,它还使任何不覆盖该函数的派生类也抽象。

所以,如果你想强制派生类实现所有这些功能,那么就让它们都是纯的。getArea如果派生类只实现而不实现其他两个是有意义的,那么只标记getArea纯。在这个例子中,我怀疑它没有意义,因为如果所有派生类都添加了一种计算面积的方法,那么基类仍然无法计算周长。

于 2012-10-23T14:49:20.717 回答
0

将方法声明为纯虚拟意味着继承您的类的类必须实现该方法或将其保留为纯虚拟,在这种情况下,派生类也将是无法实例化的抽象类。

此外,正如 Luchian 之前所说,对于每个将被继承的类,您应该始终将析构函数声明为虚拟的。

于 2012-10-23T13:44:08.460 回答