C ++ proverbs: Do not redefine the inherited non-virtual functions

Source: Internet
Author: User
C ++ proverbs: Do not redefine the inherited non-virtual functions Author: fatalerror99 Source: blog Responsible editor: Fangzhou

Suppose I tell you class (class) D from class (class) B publicly derived (Public inheritance), and in class (class) B defines a public member function (Public member function) MF. Mf parameters and return value types are irrelevant, so we assume they are all void. In other words, I mean:

Class B {
Public:
Void MF ();
...
};
Class D: Public B {...};

You don't even have to know anything about B, D, or MF. Given an object (object) x with a type of D,

D x; // X is an object of Type D

You may be surprised,

B * pb = & X; // get pointer to X
Pb-> MF (); // call MF through pointer

Different from the following:Code:

D * Pd = & X; // get pointer to X
Pd-> MF (); // call MF through pointer

In both cases, you call the member function (member function) MF in object (object) X. In both cases, the same function and object should have the same behavior, right?

Yes, it should. However, it may not. In particular, if mf is non-virtual (not virtual) and D defines its own version of MF:

Class D: Public B {
Public:
Void MF (); // hides B: MF; see item33
...
};

Pb-> MF (); // callb: MF
Pd-> MF (); // calld: MF

The two sides of this behavior are caused by the fact that non-virtual functions (non-virtual functions) such as B: MF and D: MF are statically bound (static binding) (See item 37 ). This means that because Pb is declared as the pointer-to-B type, even if, as in this example, Pb points to an object of the class inherited from B, non-virtual functions (non-virtual functions) called by petabytes are always defined in Class B.

On the other hand, virtual functions are dynamically bound (dynamic binding) (see item 37 again), so they won't happen. If mf is a virtual function, calling MF through PB or PD will result in calling D: mf, because both Pb AND Pd actually point to a type (type) D object (object ).

If you are writing class D and you have redefined a non-virtual function (non-virtual function) MF and D Objects (object) that you inherited from Class B) it is likely to show uncoordinated behavior. In particular, when MF is called, the behavior of any given D object may be like B or D, and the deciding factor is irrelevant to the object itself, but it is related to the declared type pointing to its pointer (pointer. References (references) also show inexplicable behavior like pointers (pointers.

However, this is just an argument for practice. I know what you really need is a theoretical reason that you cannot redefine inherited non-virtual functions (non-virtual functions inherited. I am very willing to help.

The previous article explains that public inheritance (Public inheritance) means that is-《C ++ proverbs: interface inheritance and implementation inheritanceThis article describes why a non-virtual function (non-virtual function) is declared as a class in a class) set an invariant over specialization (beyond the special invariant). If you apply this experience to classes (class) B and D, and non-virtual member function (non-virtual function) B :: mf, then:

Every thing that applies to B objects (object) also applies to D Objects (object), because every D Objects is-a (a) D Objects (object );

The classes (class) inherited from B must inherit both the interface (Interface) and implementation (implementation) of MF, because mf is non-virtual in B.

Now, if d re-Defines MF, there is a conflict in your design. If d really needs to implement MF different from B, and if every B objects (object) -- whatever the case -- must use B to implement MF, therefore, every d is-a (a) B is totally different. In that case, D should not be inherited from B publicly inherit (public ). On the other hand, if D must really inherit from B publicly inherit (public), and if d really needs to implement MF different from B, then MF reflects a B's invariant over specialization (beyond the special invariant) will not be true. In that case, MF should be virtual. Finally, if every d is actually-A (a) B, and if mf is really equivalent to a B's invariant over specialization (beyond the special invariant ), then d won't really need to re-define MF, and I can't even think about it.

Regardless of the rule, certain concessions must be made and an inherited non-virtual function (non-virtual function inherited) cannot be redefined unconditionally ).

If I read this article to give you the feeling of d é j à vu (deja vu), it may be because you have read 《C ++ rumor: declare the Destructor as virtual in the polymorphism base classThis article explains why Destructors (destructor) in polymorphic base classes should be virtual. If you violate that guideline (Guidelines) (for example, if you are in a polymorphic base class (polymorphism base class) declare a non-virtual destructor (non-virtual destructor). You also violate this guideline (guidelines) Because Derived classes (derived class) always re-define an inherited non-virtual function (non-virtual function obtained through inheritance): destructor of base class (base class ). This is true even for derived classes (derived classes) that do not declare destructor (destructor), because, like 《C ++ proverbs: Understand What c ++ secretly adds and calls"Destructor (destructor) is a" if you do not define your own, the compiler will generate a "member functions (member function ). In fact ,《C ++ rumor: declare the Destructor as virtual in the polymorphism base classIt is only a special case in this article, although it is important enough to propose it as an independent article.

Things to remember

· Never redefine an inherited non-virtual function (non-virtual function obtained through inheritance ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.