in the C + + learning process, then the inheritance and polymorphism of the two different from the C language characteristics you must understand that if you want to learn C + +, then inheritance and polymorphism must be understood clearly, especially polymorphic, but to understand polymorphism first you must understand the inheritance first, but even if both are very understanding, I dare not say that I have mastered C + +, because this is just the tip of the iceberg in C + +. (You may be interested to learn about the four realms of C + + mentioned on the Internet)
Gossip about this, the beginning of the formal content, about C + + inheritance, I have to inherit the content learned in the content and share with you. If there is something wrong, welcome everyone to come forward!
When I study a content, I always like to start with a definition, then guess what it does with that definition, and then try to verify my guess (not every problem, of course, when it comes to some of the more important concepts), and look at the definition: Inheritance ( Inheritance) is the most important thing that can be used in the face of an image program, which allows the programmer to expand on the basis of preserving the original class features, adding additional energy. This produces a new class, called a derived class. Inheritance presents the hierarchical structure of surface object programming, which embodies the cognitive process from simple to complex.
in other words, the so-called "inheritance" is the creation of a new class on the basis of an existing class. The existing class is called the base class or the parent class (Father Class), and the new class is called a derived class (derived class) or a subclass (son Class). a new class obtains its existing attributes from existing classes, a phenomenon known as class inheritance .
Take a look at the picture and you'll know better:
When it comes to inheritance, then you have to mention derivation, because these two concepts always come together, or who can't do without, through inheritance, a new subclass gets the attributes of the parent class from the existing parent class. from another perspective, a new subclass is generated from the existing class (the parent Class), called the derivation of the class. class inheritance is the programming technique for building specialized classes with existing classes. derived classes inherit all data members and member functions of the base class and can make the necessary additions or adjustments to the members . A base class can derive multiple derived classes, and each derived class can then derive a new derived class as a base class, so the base class and the derived class are relative. The inheritance hierarchy of a class is formed by the derivation of a generation. The equivalent of a large family, there are many branches, all descendants inherit the basic characteristics of the ancestors, while there are differences and development. Similarly, each derivation of a class inherits the basic characteristics of its base class, and adjusts and expands the original features as needed.
When the concept of what is inherited is finished, then start the next content: Inherit the definition format, take a look at the same picture
Public, protected, and private are also known as Access qualifiers, which define inheritance relationships
Let's take a look at the different access control relationships for member variables under different inheritance methods:
The following code is used to verify:
Class Base {public: base () { & nbsp; cout << "B ()" << Endl; } ~base () { cout << "B ()" << Endl; } void showbase () { cout << "_pri =" << _pri << endl; cout << "_pro =" << _pro << Endl; cout << "_pub =" << _pub << Endl; }private: int _pri; protected: int _pro; public: int _pub;}; Class Derived:p ublic Base {public: derived () { &nbSp cout << "D ()" << Endl; } ~derived () { cout << "D ()" << Endl; } void showderived () { cout << "_d_pri =" << _d_pri << endl; cout < < "_d_pro =" << _d_pro << endl; cout << "_d_pub =" << _d _pub << endl; }private: int _d_pri; protected: int _d_pro; Public: int _d_pub;};
First, let's see how the class and the parent class are related to the creation of the object, first creating a base class and an object of a derived class.
int main () {Base B; Derived D; return 0;}
we will find that after running the above program, the parent class calls its own constructor with no problem, the subclass also calls the parent class constructor, which is why? In fact, this is very simple to understand, we can make the content of the object of the subclass into two parts, part is that it inherits the content of the parent class, and part of it is its own unique content, we all know that when creating the derived class object, it will call the constructor, since it is composed of two parts, Then naturally it needs two constructors to construct it together, which is more intuitive to explain in a diagram:
It is necessary here to explain the following three tips:
1. The base class does not have a default constructor, and the derived class must explicitly give the base class name and argument list in the initialization list.
2. If the base class does not have a constructor defined, the derived class can also use the default constructor without defining it.
3. The base class defines the constructor with the formal parameter list, and the derived class must define the constructor function.
hidden with the same name
Similarly, the above two classes, we create two objects, one is the parent class object, the other is a subclass object, we can call the separate inside the
The Showbase () method and the Showderived () method obviously have no problem, but what if we change both methods to the show () method? This involves the concept of hiding with the same name!
What is hidden by the same name? The same name is hidden: two member functions (including member variables) are in different scopes, but the same name (return value, parameter list can be the same or not the same), if you want to use the object of the derived class to invoke the same name method in the base class can not be successful, but there is a workaround, is to precede the method with a scope. Take a look at the code:
Class Base {public:base () {_pri = 0x04;_pro = 0x05;_pub = 0x06;cout << "B ()" << Endl;} ~base () {cout << "~b ()" << Endl;} void/*showbase () */show () {cout << "_pri =" << _pri << endl;cout << "_pro =" << _pro <&l T Endl cout << "_pub =" << _pub << Endl;} void Show (int a) {cout << a << Endl;} Private:int _pri; Protected:int _pro; Public:int _pub;}; Class Derived:p ublic Base {public:derived () {_d_pri = 0x01;_d_pro = 0x02;_d_pub = 0x03;cout << "D ()" << en dl }~derived () {cout << "~d ()" << Endl;} void/*showderived () */Show () {cout << "_d_pri =" << _d_pri << endl;cout << "_d_pro =" << _ D_pro << endl;cout << "_d_pub =" << _d_pub << Endl;} Private:int _d_pri; Protected:int _d_pro;public:int _d_pub;}; int main () {Base b;derived d;b.show ();d. Show ();d. Show (1); You will get an error D during compilation here. Base:: Show (); A function of the same name can be accessed in such a way as return 0;}
compatibility on base classes and derived class types
Here is nothing more than two can be converted (here is the main discussion of pointers), the relationship of mutual assignment, derived classes can be assigned to the base class (it is possible to understand that the base class requires the content derived classes have, because the derived class inherits the contents of the base class), but the base class cannot directly assign a value to the derived class, A strong turn is required (provided that it is under public inheritance). Or use the class above to do the test:
int main () {Base * b;derived * d;d = new Derived;b = new base;b = D; A derived class can assign a value of B->showbase () to a base class; Calling a function is not a problem//d = &b; Error "=": Cannot convert from "Base * *" to "Derived *" D = (derived*) &b; This compiles without problems, but try not to do so, there may be unpredictable errors d->showderived (); If you use the above way will bring error, inside printed a random value d->showbase (); return 0;}
A summary of this section is:
1. Subclass objects can be assigned to parent class objects (cut/slice)
2. The parent class object cannot be assigned to a child class object
3. A pointer/reference to a parent class can point to a child class object
4. A pointer/reference to a subclass cannot point to the parent class object (can be done by forcing the type conversion )
write here a small summary before starting the next part of the content:
1. The private member of the base class is inaccessible in the derived class and is defined as protected if the base class member does not want to be accessed directly outside the class, but needs to be accessible in the derived class. You can see that the protection member qualifier occurs because of inheritance.
2. Public inheritance is an interface inheritance that maintains the is-a principle, and the members that are available to each parent class are also available, because each child class object is also a parent class object.
3. Protetced/private inheritance is an implementation inheritance, some members of a base class are not completely part of the subclass interface, and are the principle of has-a relationships, so the two inheritance relationships are not used under special circumstances and are used in most scenarios as public inheritance.
4. Regardless of the inheritance method, the public and protected members of the base class can be accessed inside the derived class, and the private members of the base class exist but are not visible in the subclass (inaccessible).
5. The default inheritance method when using the keyword class is private, and the default inheritance method when using a struct is public, but it is best to show the inheritance in the way it is written.
6. In the actual application of the general use is the public inheritance, very few scenarios will use Protetced/private inheritance.
7. A friend relationship cannot inherit, that is, the base class friend cannot access the subclass private and protected members, the base class defines the static member, and the entire inheritance system has only one such member. No matter how many subclasses are derived, there is only one static member instance. (Static members can be inherited)
Another problem is the constructor in the inheritance relationship, the problem of the destructor call process, I use a picture of clothes to indicate:
on the question of diamond inheritance
In the process of inheriting this content, will encounter a "strange" problem is about the diamond inheritance problem, since said it "strange", then how is he "strange"? Mainly because it is not common (I only see input, output stream in the implementation of the library function to use the diamond inheritance, interested can go to understand), it is because of this, causing it to appear somewhat "strange."
Let's take a look at the picture first:
When it comes to diamond inheritance, we have to talk about the concept of virtual inheritance, and for virtual inheritance, it is to solve the problem of data inconsistency in memory with different copies of the same name data members inherited from different paths, and set the common base class as the virtual base class. A data member with the same name inherited from a different path has only one copy in memory, and the same function name has only one mapping.
Class a{}; Base Classes Class B:public a{};//subclass class C:public A{};class d:public b,public C ();
As in the code of the A,b,c,d constitutes a diamond inheritance, if not the virtual base class to implement the diamond inheritance will lead to the phenomenon of fuzzy calls, so-called fuzzy call in memory in D will retain two base class A object, how to solve this problem, the use of virtual base class can be a good solution to this problem, you can instead:
Class B:virtual public a{};//subclass class C:virtual public a{};
we can take a closer look at a code:
Class Base{public:int _pub;}; Class Derived_one:/*virtual*/public base{public:int _por;}; Class Derived_two:/*virtual*/public base{public:int _pri;}; Class Derived:public Derived_one, public derived_two{public:int _num;}; int main () {Derived d;cout << sizeof (d) << Endl;return 0;}
The above code in the case of the result is not virtual inheritance is 20, it is easy to understand, but if the virtual inheritance, then the result has changed, the result becomes 24, which is why? As we all know, if the concept of virtual inheritance is not attractive, then the above code will have the problem of data ambiguity (there are two data members from the base class), but after the introduction of virtual inheritance, the ambiguity problem can be solved, or the diagram to illustrate it:
About Diamond inheritance This piece is not detailed enough, if you want to dig deeper: Learn more about Diamond inheritance (contains virtual functions)
Finally summarize the virtual inheritance:
1. Virtual inheritance solves the problem of data redundancy & wasted space of face-class objects containing multiple parent objects in a diamond-like inheritance system.
2. Virtual inheritance systems look complicated, and in practice we don't usually define such a complex inheritance system. It is generally not the last resort to define the virtual inheritance architecture of a diamond structure, because using virtual inheritance to solve data redundancy problems also leads to performance loss.
C + + Soul's---inheritance Chapter