Deep Demystification of C++ Inheritance: Understanding the Core Concepts of Object-Oriented Programming

1. Inheritance

1. Inheritance and object-oriented

We know that C language is a process-oriented programming language, and C++ has evolved an object-oriented model based on C language. Inheritance is an important attribute of object-oriented . Inheritance allows us to expand on a basic attribute to describe many transactions that have the same basic attributes but are different.

2. Inherited access rights

There are three types of inheritance methods that are the same as access rights: public, private, and protected inheritance. Combined with the three access rights of the base class, there are nine different situations in the derived class. It can be summarized as follows: members of the base class that are private are in Derived classes are always invisible, and other permissions are smaller than those of inheritance.

3. Slicing (assignment conversion)

In actual application scenarios, we often use base classes to represent the basic attributes common to several transactions, and derived classes to represent their own unique attributes. This will lead to the fact that the derived class object must contain the parent class object, so the subclass object can be assigned to Parent class object/pointer/reference , the process will cut out the unique attribute members in the subclass, and assign the remaining to the parent class object, so it is called slicing . Not only that, the pointer of the base class can be assigned to the pointer of the derived class through forced type conversion. , the code demonstration is as follows:

class Person
{
    
    
protected:
	string _name; 
	string _sex;
	int _age; 
};

class Student : public Person
{
    
    
public:
	int _No;
};

void Test()
{
    
    
	Student sobj;
	// 子类对象可以赋值给父类对象/指针/引用
	Person pobj = sobj;
	Person* pp = &sobj;
	Person& rp = sobj;


	// 基类的指针可以通过强制类型转换赋值给派生类的指针
	pp = &sobj;
	Student * ps1 = (Student*)pp; // 这种情况转换时可以的。
	ps1->_No = 10;

	pp = &pobj;
	Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以,但是会存在越界访问的问

	ps2->_No = 10;
}

int main()
{
    
    
	Test();
	return 0;
}

4.Scope

If a function with the same name is defined in a base class and a derived class, it will constitute hiding/redefinition , and the subclass members will shield the parent class from direct access to members with the same name, as shown below;

class A
{
    
    
public:
	A(int num = 0)
	:_num(num)
	{
    
    }

	void func()
	{
    
    
		cout << _num << endl;
	}
private:
	int _num;
};


class B : public A
{
    
    
public:
	B(int val = 1)
		:_val(val)
	{
    
    }

	void func()
	{
    
    
		cout << _val<< endl;
	}
private:
	int _val;
};

int main()
{
    
    
	B b;
	b.func();
	b.A::func();
	return 0;
}

5.Default member function

Inheritance follows a rule: construction is preceded by the father and then the son, and destruction is preceded by the son and the father. Because the derived class must contain objects of the base class, the constructor of the derived class must call the constructor of the base class to initialize some members of the base class. If the base class does not have a default constructor (no parameters, full default
,
compiler default generated ), the call must be made explicitly during the initialization list phase of the derived class constructor.
The copy constructor of the derived class must call the copy constructor of the base class to complete the copy initialization of the base class.
The operator= of the derived class must call the operator= of the base class to complete the copy of the base class.
After the destructor of the base class is called,
the destructor of the base class will be automatically called
. It cannot be called explicitly in the derived class, otherwise the order of destruction first of the child and then of the parent cannot be guaranteed.

6.Friends and static functions

Friend relationships will not be inherited, and static functions will not be instantiated multiple times.

7. Solve the ambiguity and data redundancy of diamond inheritance

Diamond inheritance is a special case of multiple inheritance. We should avoid diamond inheritance when writing code:
insert image description here
As shown in the figure above, it is a diamond inheritance. This will result in two copies of members of class P in class A. This will not only cause It is a waste of space and will create ambiguity . If I access the members in P through the A object, there will be ambiguity because there are two copies of the members in P in class A. To solve this problem, virtual inheritance emerged . As shown in the figure below:
insert image description here
How is virtual inheritance accomplished: Create a virtual base table in class d , place the original redundant objects at the bottom of the d object space, and store the current position and space where B and C originally stored A. The offset of the bottom A object ensures that it can be accessed when the specified B or C object accesses _a.

8. Inheritance and composition

Compared with inheritance, composition has a lower degree of coupling and is more suitable for us to use! Inheritance is also called white-box reuse , and combination is called black-box reuse , because when using combination, you cannot see the internal design of the class.
insert image description here

Guess you like

Origin blog.csdn.net/qq_43289447/article/details/131936530