Item 33: Avoid overwriting "the name obtained by inheritance"

Source: Internet
Author: User

 

 

 

Shakespeare has a saying about the name. "What's in a name? "He asked," A rose by any other name wocould smell as sweet. "(in the second scene of" Romeo and Juliette ", Mr. Zhu shenghao translated:" The name is meaningless. We call it the Rose Flower. If we change the name, the fragrance is the same." Mr. Liang Shiqiu translated: "What is the surname? We call it rose. We can change the name to the same fragrance ." -- Translator's note ). Shakespeare also wrote "He that filches from me my good name... makes me poor indeed. "(in the third scene of" Luo June ", Mr. Zhu shenghao translated:" But who stole my reputation, he is not rich because of this, I became extreme poverty because I lost it." Mr. Liang Shiqiu: "But if he takes away my reputation, it will be a loss to me if he does not have any advantage ." -- Translator's note ). Well, in C ++, what kind of attitude should we use to treat the inherited name?

The essence of things has nothing to do with inheritance. It is related to the scope. We all know that it is like this in code,

Int X; // global variable

Void somefunc ()
{
Double X; // local variable

STD: CIN>X; // Read a new value for local X
}

The statement for reading X refers to the local variable X, rather than the global variable X, because the name of the inner scope overwrites the name of the outer scope. We can visually display the status of the scope as follows:

 

When the compiler encounters the name X in the scope of somefunc, they patrol the local scope to see if there is anything called this name. Because there are, they no longer check other scopes. In this example, the X type of somefunc is double, and the global X type is int, but this does not matter. The name-hiding rule of C ++ only overwrites that name. It does not matter whether the type of the corresponding name is the same. In this example, a double name named x overwrites an int name named X.

After joining inheritance. We know that when we refer to something in the base class in a derived class member function (for example, a member function, a typedef, or a data member, the compiler can find what we are referring to because derived classes inherits from what is declared in base classes. The actual operation method is to nest the scope of the derived class in the base class scope. For example:

Class base {
PRIVATE:
Int X;

Public:
Virtual void mf1 () = 0;
Virtual void mf2 ();
Void mf3 ();

...
};

Class derived: public base {
Public:
Virtual void mf1 ();
Void mf4 ();

...
};

 

In this example, both public and private names are included, and data members and member functions are included. Member functions includes both pure virtual, simple (impure) virtual, and non-virtual. This is to emphasize that what we are talking about is about names. The example can also contain other types of names, such as enums, nested classes, and typedefs. The only important thing in this discussion is "they are names ". It is irrelevant to the name of what they are. This example uses single inheritance, but once you understand what will happen under single inheritance, C ++'s behavior under multiple inheritance is easy to predict.

Assume that mf4 is implemented in derived class, some of which are as follows:

Void derived: mf4 ()
{

...
Mf2 ();

...
}

When the compiler sees the use of the name mf2, it must determine what it refers. It does this by searching for the scope defined by something named mf2. First, it searches for the local scope (that is, the scope of mf4), but it does not find the declaration of anything called mf2. Then it searches for its contained scope, that is, the scope of class derived. It still does not find anything called mf2, so it moves up to its upper layer containing scope, that is, the scope of base class. Where it finds something named mf2, so the search stops. If there is no mf2 in the base, the search will continue. The first is the namespace (s) containing the base (if any), and the last is the global scope.

Although the process I just described is correct, it is not a complete description of how the name in C ++ is found. In any case, we did not aim to fully understand the name search issue when writing a compiler. But to fully understand how to avoid surprising incidents, we already have a lot of information about this task.

Consider the previous example again, and this time we overload mf1 and mf3, and add an mf3 version for derived. (As explained in item 36, derived's overload of mf3-a non-virtual function obtained through inheritance makes this design suspicious immediately, but out of concern about the visibility of the name under inheritance, we pretend not to see it .)

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 ();
...
};

 

The behavior caused by the above Code will surprise every C ++ programmer who has encountered it for the first time. Scope-based name hiding rule will not change, therefore, all functions named mf1 and mf3 in the base class are overwritten by the functions named mf1 and mf3 In the derived class. From the perspective of name search, base: mf1 and base: mf3 are no longer inherited by derived!

Derived D;
Int X;

...
D. mf1 (); // fine, callderived: mf1
D. mf1 (x); // error! Derived: mf1 hides base: mf1
D. mf2 (); // fine, callbase: mf2

D. mf3 (); // fine, callderived: mf3
D. mf3 (x); // error! Derived: mf3 hides base: mf3

As you can see, even if the base and derived classes functions have different parameter types, they also apply, regardless of whether the function is virtual or non-virtual. Similar to the principle that "at the beginning of this item, double X in the somefunc function overwrites int X in the global scope, here, the mf3 function in derived overwrites a base function named mf3 of different types.

Item 33: Avoid overwriting "the name obtained by 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.