Clause 32: Determine your public inheritance mold out is-a relationship
One of the most important rules for object-oriented programming in C + + is that public inheritance (common inheritance) means is-a (is a) relationship.
In the C + + domain, any function that expects to obtain an argument of the type base class (regardless of whether it is a pointer or a reference) is willing to accept a derived class object (regardless of whether it is a pointer or a reference). (Only public inheritance is established.) A good interface prevents invalid code from being compiled, so you should rather take the design of "reject at compile time" rather than the "run-time detect" design. Is-A is not the only relationship that exists between classes. Another two common relationships are has-a (there is one) and is-implemented-in-term-of (which is implemented according to something).
Please remember:
"Public inheritance" means is-a. Everything that applies to base class must also apply to derived class, because each derived class object is also a base class object.
Article 33: Avoid hiding the inherited name
Under the inheritance system, the scope of a derived class is contained under the scope of the base class, so a variable of the same name in the derived class obscures the base class's variable.
Class Base{private:int x;public:virtual void Mf1 () = 0;virtual void mf1 (int); virtual void mf2 (); void mf3 (); void Mf3 (double );...}; Class derived:public base{public:virtual void Mf1 (), void Mf3 (), void Mf4 (), ...};D erived d;intx;...d.mf1 ();//ok, Call DERIVED::MF1 () d.mf1 (x); Errord.mf2 (); OK, call BASE::MF2D.MF3 (); OK, call DERIVED::MF3D.MF3 (x); Error
All functions named MF1 and MF3 in the base class are obscured by the function with the same name in the derived class, even if they have different parameter types, even if they are virtual or non-virtual functions.
Because the above is public inheritance, in order to be able to use a function with the same name in the base class (that is, to maintain a is-a relationship), there are two ways: using a using declaration or a pass-through function.
1. In the example above, the derived class can make the following modifications: Class Derived:public base{public:using base::mf1;//Let using MF3 in everything named Mf1 and Base::mf3 in the Base class; /visible in Derived scope virtual void mf1 (), void Mf3 (), void Mf4 (), ...};D erived d;intx;...d.mf1 (); OK, call DERIVED::MF1 () d.mf1 (x); OK, call BASE::MF1 (int) d.mf2 (); OK, call BASE::MF2 () d.mf3 (); OK, call DERIVED::MF3 () d.mf3 (x); OK, call BASE::MF3 (int) This means that if you inherit the base class and want to reload the base class functions, and you want to redefine or overwrite some of them, introduce a using declaration for each name that would otherwise be obscured. 2. If you attempt to selectively inherit only partially overloaded functions, this cannot occur under public inheritance, because it violates the is-a relationship implied by public inheritance, but may make sense under private inheritance. For example, the derived inherits base with private, and the only mf1 that derived want to inherit is the parameterless version. The using declaration is useless here, because all functions of the same name that he declares are visible in Derived, and can be used with the transfer function (forwarding functions): Class Derived:private base{//Private inheritance, is-implemented-in-term-of relationship public:virtual void Mf1 () {//Transfer function BASE::MF1 ();} ...};D erived d;intx;...d.mf1 (); OK, call DERIVED::MF1 () d.mf1 (x); ERROR,BASE::MF1 is blocked
Please remember:
The name within the derived calsses will obscure the name within the base classes. No one has ever wished to do so under public inheritance.
To let the masked name see the daylight, use a using declarative or a transfer function (forwarding functions).
Article 34: Differentiating between interface inheritance and implementation inheritance
Superficially straightforward public inheritance concept, after more rigorous inspection, found that it consists of two parts: function interface inheritance and function implementation inheritance. The interface of the member function is always inherited.
The pure virtual function has two most prominent features: they must be re-declared by any of the "inherited" class-like classes, and they are usually not defined in the abstract class. So: The purpose of declaring a pure virtual function is to have derived class inherit only the function interface.
Surprisingly, we can provide definitions for pure virtual functions. But the only way to invoke it is "explicitly stating its class name when called":
The purpose of declaring a simple (non-pure) impure virtual function is to have derived class inherit the interface and default implementation of the function.
The purpose of declaring the Non-virtual function is to make the interface of the derived class inheritance function and a mandatory implementation.
If the member function is a non-virtual function, it means that it is not intended to behave differently in derived classes.
Please remember:
Interface inheritance differs from implementation inheritance. Under public inheritance, derived classes always inherits the interface of base class.
The pure virtual function only specifically formulates interface inheritance.
The simple (non-pure) impure virtual function specifically formulates interface inheritance and default implementation inheritance.
The Non-virtual function specifically formulates interface inheritance and implements inheritance in a mandatory context.
Article 35: Consider alternatives other than the virtual function
Article 36: Never redefine inherited non-virtual functions
Please remember:
Never redefine the inherited non-virtual function.
Article 37: Never redefine inherited default parameter values
Please remember:
Never redefine the inherited default parameter values, because the default parameter values are static bindings, and the virtual function-the only thing you should overwrite-is dynamic binding.
Clause 39: Use private inheritance wisely and prudently
Please remember:
1.private inheritance means is-implementation-in-terms of (according to something). She is usually lower than the compound level. However, this design is reasonable when derived class needs to access the members of the protected base class or need to redefine the inherited virtual functions.
2. Unlike compounding, private inheritance can result in the optimization of empty base. This may be important for library developers who are committed to minimizing the size of objects.
Article 40: Use multiple inheritance wisely and prudently
Please remember:
1. Multiple inheritance is more complex than single inheritance. It can lead to new ambiguity and the need for virtual inheritance.
2.virtual inheritance increases the cost of size, speed, initialization (and assignment) complexity, and so on. If virtual base class does not carry any data, it will be the most useful case.
3. Multiple inheritance does have a legitimate purpose. One of the episodes involves the two-phase combination of "public inheriting a interface class" and "private inheriting a class of assistance implementations."
Effective C + + terms 32~40 "inheritance and object-oriented design" collation