Define base and derived classes
We first complete the definition of base class and derived class:
We first define a class named Quote as the base class to represent books sold at the original price, bulk_ The class of Quote, as a derived class, represents books that can be sold at a discount. These classes contain two functions: isbn() represents the ISBN number of the book, and netPrice() represents the actual selling price.
class Quote { public: Quote() = default; Quote(const string &s, double d):_isbn(s), _price(d){} virtual double netPrice(int n) const { return _price * n; } private: string _isbn = "x"; protected: double _price = 0.0; }; class BulkQuote : public Quote { //Public inherited Quote public: BulkQuote() = default; BulkQuote(const string &s, double d, int b, double dis): Quote(s, d), _minBuy(b), _discount(dis){} double netPrice(int n) const override { if (n > _minBuy) { return n * _discount * _price; } return n * _price; } private: int _minBuy; //Minimum purchase quantity double _discount; //Discount amount in decimal };
1. Define base class
Base classes should usually define a virtual destructor, even if the function does not perform any actual operations.
① There are two member functions of the base class:
Functions that the base class wants the derived class to override (virtual functions):
- When I call a virtual function with a pointer or reference, the call will be bound dynamically: depending on the object type bound by the reference or pointer, the call may execute the version of the base class or the version of a derived class.
- Virtual function is to add the keyword virtual before the member function declaration statement to make the function perform dynamic binding. Virtual can only appear before the declaration statement inside the class, not for function definitions outside the class.
- The virtual function parsing process occurs at run time.
Functions that the base class wants the derived class to inherit directly:
- Static member function parsing occurs at compile time.
② Access control and inheritance
A derived class can inherit members defined in the base class, but does not necessarily have access to members inherited from the base class. Derived classes can access the public and protected members of the base class, but not the private members of the base class.
2. Define derived classes
① Virtual functions in derived classes
A derived class often overrides the virtual functions it inherits, but it does not have to. If it does not override the virtual functions it inherits from the base class, like other ordinary members, the derived class will directly inherit the version of the base class.
The derived class explicitly defines an overridden virtual function with the keyword override.
② Type conversion of derived class objects and derived classes to base classes
A derived class contains multiple components:
- A child object of a member defined by the derived class itself.
- The child object corresponding to the base class inherited by the derived class.
For example, BulkQuote contains its own defined sub objects_ minBuy,_ discount and child objects inherited from the base class Quote_ isbn and_ price.
Because the derived class object contains components corresponding to its base class, we can use the derived class object as a base class object, and bind the pointer or reference of the base class to the base class part of the derived class object. This conversion is called a type conversion from a derived class to a base class. The compiler implicitly performs the conversion from derived class to base class.
③ Derived class constructor
The derived class inherits the constructor of the base class from the base class. The derived class object cannot directly initialize the members of the base class, but should initialize the members inherited from the base class through the interface of the base class (constructor of the base class).
For example, the constructor of BulkQuote
BulkQuote(const string &s, double d, int b, double dis): Quote(s, d), _minBuy(b), _discount(dis){}
Pass its first two parameters to the constructor of the Quote. The Quote initializes the base class part of BulkQuote, and then initializes the members directly defined by the derived class.
④ Declaration of derived classes
The declaration of a derived class is not different from other classes. The Declaration contains the class name, but does not contain its derived list.
class BulkQuote : public Quote; //Error: declaration cannot contain a derived list class BulkQuote; //Correct: the correct way to declare a derived class
The purpose of declaration statement is to make the program know the existence of a name and what kind of entity the name represents, such as a class, a function or a variable. The derived list and other details about predefinition must appear with the definition of the class.
⑤ Class used as base class
If we use a class as a base class, the class must already be defined, not just declared:
class Quote; //Declared but undefined class BulkQuote : public Quote {...} //Error: Quote must already be defined
⑥ Prevent inheritance
Sometimes we define such a class. We don't want other classes to inherit it, or we don't want to consider whether it is suitable to be a base class. As long as we add a final after the class name:
class NoDerived final {...} //NoDerived cannot be used as a base class