1 Public inheritance
When a derived class is publicly inherited from (public inheritance) base class, inheritance consists of two parts: the first is the "interface" of the function (interface), and the second is the "implementation" of the function (Implementation)
There are three different forms of member functions in a base class Shape, representing three cases of public inheritance
classShape { Public: Virtual voidDraw ()Const=0; Virtual voidErrorConstSTD::string&msg); intObjectID ()Const;};classRectangle: PublicShape {...};classEllipse: PublicShape {...};
1.1 Pure virtual function
The end of the virtual function is prefixed with "= 0", declared as pure virtual function, which represents the interface (interface) of the base class member function inherited by the derived class, and the implementation of the function is overridden in the derived class (Implementation)
At the same time, a base class contains a pure virtual function, then the base class is an abstract base class, which is not instantiated.
New // error! Shape is abstract
The following code, called the derived class Rectangle and Ellipse, has their own overridden (override) member function Rectangel::D raw and Ellipse::D Raw
New Rectangle; Ps1->draw (); // calls Rectangle::d rawnew Ellipse; Ps2->draw (); // calls Ellipse::d raw
Of course, if you want to call a member function of a base class, you can add a class scope operator:
// calls Shape::d Raw // calls Shape::d Raw
1.2 General virtual functions
Before the function declaration is appended with the virtual keyword, and there is no "= 0" at the end, the function is a generic virtual function that requires a default implementation (implementation) defined in the base class
A generic virtual function that indicates that the derived class inherits the interface of the base class member function and the default implementation, and that the derived class can choose whether to override the implementation of the function (Implementation)
In fact, it is dangerous to allow a generic virtual function to inherit both the interface and the default implementation , as in the following example: Modela and Modelb are the two aircraft types of airplane, and both fly in the same way
classAirport {...};//represents airportsclassAirplane { Public: Virtual voidFlyConstairport&destination);};voidAirplane::fly (Constairport&destination) { //default code for flying a airplane to the given destination}classModela: Publicairplane {...};classModelb: PublicAirplane {...};
This is a typical object-oriented design, two class sharing (share) a common feature (feature)-fly, then fly can be implemented in the base class, and by two derived classes of the public inheritance
Now add a new aircraft model MODELC, its flight mode and MODELA,MODELB is not the same, if you accidentally forgot to rewrite the new fly function in MODELC
class Public Airplane { // no fly function is declared};
The fly function in MODELC is called Airplane::fly, but Modelc's flight style is not the same as the default.
// PDX is the airport New modelc;pa// calls airplane::fly!
This is what is said earlier, it is dangerous to inherit the interface and the default implementation at the same time , it is best to implement the default behavior (behavior) in the base class, but provide the default behavior only when the derived class requires it.
One method is that the pure virtual function + default implementation , because it is a pure virtual function, so only the function interface is inherited by the derived class, its default implementation is not inherited by the derived class, the derived class to use the default implementation, you must explicitly call
classAirplane { Public: Virtual voidFlyConstairport& destination) =0;};voidAirplane::fly (Constairport&destination) { //a pure virtual function default code for flying an airplane to the given destination}classModela: PublicAirplane { Public: Virtual voidFlyConstairport&destination) {airplane::fly (destination);}};classModelb: PublicAirplane { Public: Virtual voidFlyConstairport&destination) {airplane::fly (destination);}};
This way, in a derived class MODELC, even if you accidentally forget to override the Fly function, the default implementation of airplane is not invoked, causing unnecessary loss
class Public Airplane {public: virtualvoid Fly (const airport& destination);}; void Modelc::fly (const airport& destination) { // code for flying a MODELC Airplane to the given destination}
As you can see, the key to the above problem is to accidentally forget to rewrite the fly function in the derived class MODELC, anduse the keyword override in c++11 to avoid such "accidentally"
1.3 Non-virtual member functions
The non-virtual member function does not have the virtual keyword, which means that the derived class not only inherits the interface of the base class member function, but also inherits a mandatory implementation of the function (mandatory implementation)
Since inheritance is a mandatory implementation, it is now required that in derived classes, do not redefine (redefine) inherited member functions from the base class , as follows:
class B {public: void MF ();}; class Public B {...};
The MF function is called using the pointer, which is called the B::MF ()
// x is an object of type D // get pointer to x// call MF through pointer// get Pointer to x// call MF through pointer
What if the member functions that inherit from the base class are redefined in the derived class MF?
class Public B {public: void// hides b::mf; see Item33};p b // calls B::MF // calls D::MF
At this point, the redefined member function in the derived class "hides" (hide) inherits the member function from the base class
This is because non-virtual functions are "statically bound", PB is declared to be a pointer of type b*, and non-virtual functions that are called by PB are in base class B, so that PB points to a derived class D
the "static binding" is relative to the "dynamic binding" of a virtual function, that is, whether or not PB is declared as b* or d* type, the virtual function of its invocation depends on the type of object that PB actually points to.
2 Rewrite (override)
As mentioned in 2.2, the override keyword avoids the error of overriding a virtual function in a derived class, with the base base class and the Derived derived class as an example to elaborate
classBase { Public: Virtual voidMF1 ()Const; Virtual voidMF2 (intx); Virtual voidMF3 () &; voidMF4 ()Const;//Is isn't declared virtual in Base};classDerived: PublicBase { Public: Virtual voidMF1 ();//declared const in Base, but not in Derived. Virtual voidMF2 (unsignedintx);//takes an int in Base, but a unsigned int in Derived Virtual voidMF3 () &&;//is lvalue-qualified on Base, but rvalue-qualified in Derived. voidMF4 ()Const; };
In a derived class, overriding (override) inherits from the implementation of the base class member function (Implementation) to meet the following conditions:
One virtual : The member function is declared virtual in the base class
two capacity : in base classes and derived classes, the return type and Exception specification (exception specification) of member functions must be compatible
Four with : in base and derived classes, member function names, parameter types, constant attributes (constness), and reference qualifiers (reference qualifier) must be fully
So many constraints, resulting in a virtual function rewrite like the above code, is extremely easy because of an careless error
Instead, the override keyword in c++11 can be declared in an explicit derived class, which member functions need to be overridden, and if not overridden, the compiler will make an error
classDerived: PublicBase { Public: Virtual voidMF1 ()Override; Virtual voidMF2 (unsignedintXOverride; Virtual voidMF3 () &&Override; Virtual voidMF4 ()Const Override;};
In this way, even if accidentally omitted to write a virtual function rewrite some of the harsh conditions, you can also through the compiler error, quickly correct errors
classDerived: PublicBase { Public: Virtual voidMF1 ()Const Override; Virtual voidMF2 (intXOverride; Virtual voidMF3 ()& Override; voidMF4 ()Const Override;//adding "virtual" is OK, and not necessary};
Summary:
1) Public inheritance:
Pure virtual function = Inheritance of interface
Impure virtual function = Inheritance of interface plus default implementation
non-virtual function = Inheritance of interface plus madatory implementation
2) never redefine an inherited non-virtual function
3) Declare overriding functions override
Resources:
<effective c++_3rd> Item, item 36
<effective Modern C++> Item 12
C++11 's override keyword