Team LiB
Previous Section Next Section

15.6. Pure Virtual Functions

15.6. 纯虚函数

The Disc_item class that we wrote on page 583 presents an interesting problem: That class inherits the net_price function from Item_base but does not redefine it. We didn't redefine net_price because there is no meaning to ascribe to that function for the Disc_item class. A Disc_item doesn't correspond to any discount strategy in our application. This class exists solely for other classes to inherit from it.

第 15.4.2 节所编写的 Disc_item 类提出了一个有趣的问题:该类从 Item_base 继承了 net_price 函数但没有重定义该函数。因为对 Disc_item 类而言没有可以给予该函数的意义,所以没有重定义该函数。在我们的应用程序中,Disc_item 不对应任何折扣策略,这个类的存在只是为了让其他类继承。

We don't intend for users to define Disc_item objects. Instead, Disc_item objects should exist only as part of an object of a type derived from Disc_item. However, as defined, there is nothing that prevents users from defining a plain Disc_item object. That leaves open the question of what would happen if a user did create a Disc_item and invoked net_price function on it. We now know from the scope discussion in the previous section that the effect would be to call the net_price function inherited from Item_base, which generates the undiscounted price.

我们不想让用户定义 Disc_item 对象,相反,Disc_item 对象只应该作为 Disc_item 派生类型的对象的一部分而存在。但是,正如已定义的,没有办法防止用户定义一个普通的 Disc_item 对象。这带来一个问题:如果用户创建一个 Disc_item 对象并调用该对象的 net_price 函数,会发生什么呢?从前面章节的讨论中了解到,结果将是调用从 Item_base 继承而来的 net_price 函数,该函数产生的是不打折的价格。

It's hard to say what behavior users might expect from calling net_price on a Disc_item. The real problem is that we'd rather they couldn't create such objects at all. We can enforce this design intent and correctly indicate that there is no meaning for the Disc_item version of net_price by making net_price a pure virtual function. A pure virtual function is specified by writing = 0 after the function parameter list:

很难说用户可能期望调用 Disc_itemnet_price 会有什么样的行为。真正的问题在于,我们宁愿用户根本不能创建这样的对象。可以使 net_price 成为纯虚函数,强制实现这一设计意图并正确指出 Disc_itemnet_price 版本没有意义的。在函数形参表后面写上 = 0 以指定纯虚函数:

     class Disc_item : public Item_base {
     public:
         double net_price(std::size_t) const = 0;
     };

Defining a virtual as pure indicates that the function provides an interface for sub-sequent types to override but that the version in this class will never be called. As importantly, users will not be able to create objects of type Disc_item.

将函数定义为纯虚能够说明,该函数为后代类型提供了可以覆盖的接口,但是这个类中的版本决不会调用。重要的是,用户将不能创建 Disc_item 类型的对象。

An attempt to create an object of an abstract base class is a compile-time error:

试图创建抽象基类的对象将发生编译时错误:

     // Disc_item declares pure virtual functions
     Disc_item discounted; // error: can't define a Disc_item object
     Bulk_item bulk;       // ok: Disc_item subobject within Bulk_item

A class containing (or inheriting) one or more pure virtual functions is an abstract base class. We may not create objects of an abstract type except as parts of objects of classes derived from the abstract base.

含有(或继承)一个或多个纯虚函数的类是抽象基类。除了作为抽象基类的派生类的对象的组成部分,不能创建抽象类型的对象。



Exercises Section 15.6

Exercise 15.26:

Make your version of the Disc_item class an abstract class.

使你的 Disc_item 类版本成为抽象类。

Exercise 15.27:

Try to define an object of type Disc_item and see what errors you get from the compiler.

试试定义 Disc_item 类型的一个对象,看看会从编译器得到什么错误。


Team LiB
Previous Section Next Section