15.6. Pure Virtual FunctionsThe 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. 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. 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: 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. 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
![]() |