Detailed explanation of inheritance in C++

[TOC]

Inherit the basics

definition:

Inheritance is an important means  for reuse . A class is defined by inheritance. Inheritance is the modeling of the relationship between types, sharing common things, and implementing things that are essentially different.

Inheritance relationship:

 Changes in the access relationship of the base class members in the derived class under the three inheritance relationships (Figure)
Alt text
 Take a chestnut (public inheritance)

```c++
class Person
{
public :
Person(const string& name)
: _name(name )
{}
void Display ()
{
cout<<_name <<endl;
}
protected :
string _name ; // 姓名
string _sex ;
};

class Student : public Person // public inheritance
{
protected :
int _num ; // student number
};

### 继承图例解释:
![这里写图片描述](https://img-blog.csdn.net/2018042122253862?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
**私有继承和保护继承很少用到,我们重点要掌握公有继承**

### 继承与转换--赋值兼容规则--public继承
1. 子类对象可以赋值给父类对象(切割/切片)
2. 父类对象不能赋值给子类对象
3. 父类的指针/引用可以指向子类对象
4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成)
```C++
class Person
{
public:
    void Display()
    {
        cout << "AA" << endl;
    }
protected:
    string _name; // 姓名
};
class Student : public Person
{
public:
    int _num; // 学号
};

int main()
{
    Person a;
    Student b;
    a = b; //子类对象赋值给基类对象(切片)这个特性是编译器支持的
    b = a; //父类对象不能赋值给子类对象

    Person *p1 = &b; //特性3
    //Person &a1 = b; //特性3
    Student *p2 = (Student*)&a; //特性4
    Student& b1 = (Student&)a; //特性4
    getchar();
    return 0;
}

Scope in Inheritance Hierarchy

  1. Base and derived classes have separate scopes in an inheritance hierarchy.
  2. Subclass and superclass have members with the same name (member functions, member variables) subclass members will block direct access to members of the superclass. (In the subclass member function, you can use the base class::base class member access) -- hidden (redefinition)
  3. ==Note that in practice it is best not to define members with the same name== in the inheritance system.
    
    class Person
    {
    public:
    Person(const char *name = "",int num = 0)
        :_name(name)
        ,_num(num)
    {}

protected:
string _name; // name
int _num;
};
class Student : public Person
{
public:
Student(const char* name = "", const int num1 = 0, int num2 = 0)
:Person(name,num1)
, _num(num2)
{}
void Display()
{
cout << _num << endl;
cout <<Person:: _num << endl;//The base class scope must be displayed to print the base class members
}
protected:
int _num; // student number
};

int main()
{
Person a("boday",15);
Student b("crash",1502,17);
b.Display();

return 0;

}

**运行结果:**
![这里写图片描述](https://img-blog.csdn.net/20180422193345134?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
可以很明显看出此时打印的是子类的成员,而隐藏掉了父类的成员,(```这就是隐藏```)

### 派生类的默认成员函数
&#8195;在继承关系里面,在派生类中如果没有显示定义这六个成员函数,编译系统则会默认合成这六个默认的成员函数。
![这里写图片描述](https://img-blog.csdn.net/20180421222558568?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM4NjQ2NDcw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
**来个栗子说说默认成员函数的前四个(` 后两个不常用`)**
```cpp
class Person
{
public:
    Person(const char *name = "",int num = 0) //父类构造函数
        :_name(name)
        ,_num(num)
    {}
    ~Person()//父类析构函数
    {
        cout << "~Person()" << endl;
    }
    Person(const Person& p)//父类拷贝构造函数
        :_name(p._name)
        ,_num(p._num)
    {}
    Person& operator=(const Person& p)//父类赋值运算符重载
    {
        if (this != &p)
        {
            _name = p._name;
            _num = p._num;
        }
        return *this;
    }

protected:
    string _name; // 姓名
    int _num;
};
class Student : public Person
{
public:
    Student(const char* name = "", const int num1 = 0, int num2 = 0)//子类构造函数
        :Person(name,num1)   
        ,_num(num2)
    {}
    ~Student()//子类析构函数
    {
        cout << "~Student()" << endl;
    }
    Student(const Student& s)//子类拷贝构造函数
        :Person(s)
        ,_num(s._num)
    {}
    Student& operator=(const Student& s)//子类赋值运算符重载
    {
        Person::operator=(s); //显示调用父类赋值运算符重载
        _num = s._num;
    }
protected:
    int _num; // 学号
};

先调用父类构造函数,在调用基类构造函数;析构函数调用顺序与构造函数相反(先构造后析构,这个和栈的规则有关(先入后出))

Inheritance method (single inheritance, multiple inheritance, diamond inheritance)

write picture description here

1. Single inheritance

Definition: When a subclass has only one direct parent class, the inheritance relationship is called single inheritance

Code example:

class A
{
protected:
    int _a;
};

class B : public A //B类 继承 A类
{
protected:
    int _b;
};

2. Multiple inheritance

Definition: When there are two or more subclasses 直接父类, the inheritance relationship is called multiple inheritance

Code example:

class A
{
protected:
    int _a;
};

class B 
{
protected:
    int _b;
};

class C : public A,B
{
protected:
    int _c;
};

3. Diamond Inheritance

Code example:

class Person
{
public:
    string _name; // 姓名
};
class Student : public Person
{
protected:
    int _num; //学号
};
class Teacher : public Person
{
protected:
    int _id; // 职工编号
};
class Assistant : public Student, public Teacher
{
protected:
    string _majorCourse; // 主修课程
};
void Test()
{
    // 显示指定访问哪个父类的成员(二义性问题)
    Assistant a;
    a.Student::_name = "xxx";
    a.Teacher::_name = "yyy";//数据冗余问题
}

Obviously there is a problem with diamond inheritance, there are problems of ambiguity and data redundancy. To solve this problem, virtual inheritance was introduced.

Virtual Inheritance: Solving the Ambiguity and Data Redundancy of Diamond Inheritance

When declaring a derived class, specify its inheritance method as a virtual inheritance method. Such as

class A
{
public:
    int _a;
};

class B : virtual public A //声明为虚基类
{
protected:
    int _b;
};

class C : virtual public A //声明为虚基类
{
protected:
    int _c;
};

class D : public B,public C
{
protected:
    int _d;
};

Check out the test results:

void Test()
{
    D d;
    d._a = 10;
}

write picture description here
Are you wondering how to solve it? Then we need to go deep into the underlying exploration.
write picture description here
Here, a virtual base table is used to store the offset during virtual inheritance, so that classes B and C use a virtual base table to store the offset of A relative to B and C. When virtual inheritance occurs Time A will be stored in a public area, which solves the problem of ambiguity and saves space at the same time.
Virtual inheritance is a good solution to the problems caused by diamond inheritance.

It is recommended that you write down the code to debug it, and check the memory changes at the same time.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326791831&siteId=291194637