bosthhe1 / cpushpush

0 stars 0 forks source link

继承 #21

Open bosthhe1 opened 1 year ago

bosthhe1 commented 1 year ago

继承是为了将共同信息提取出来,封装到一个类里面,就好像函数复用一样,比如将经常使用到交换,就将交换提取出来封装成swap函数,大家都可以调用,减少代码冗余,继承也和函数类似,但是继承会存在一些权限控制 3_FYR245_I2 ~$}Z_X7 HKM

一般的继承方式我们都是设置成public,很少使用protected和private 虽然父类的成员函数是私有的,不可见的,但是父类的私有成员也会继承给子类,占子类的空间,只不过子类无法访问

bosthhe1 commented 1 year ago
    struct common//默认类的成员变量和函数是共有的
    {
        common(int id = 10)
        :_id(id)
        {}
        int _id;
    };
    class student : public common//这里的继承方式是public
    {
    public:
        student(int stud=10, int id = 1013456)
        :common(id)//初时化继承的变量,方法和调用匿名函数相似
        ,_stud(stud)
        {}
    private:
        int _stud;
    };
bosthhe1 commented 1 year ago

子类因为包含父类的所以信息,所以子类可以初始化父类,但是不属于父类的一部分会丢失,这种叫做切片,图片中id就缺失了,而且切片只能发生在子类到父类中,不能调换,切片同时发生在指针上,将父类类型的指针,指向子类的地址,也会发生切片 image image image

bosthhe1 commented 1 year ago

继承同时也分为很多种类,单继承和多继承,而多继承就涉及菱形继承 image 单继承的书写形形式

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

image 多继承的书写方式

class C :public A, public B//中间需要逗号隔开,C中包含A,B类的成员
    {
    public:
        int _c;
    };

image 存在多继承,就必然存在菱形继承,这个D里面继承了B,C,然而B,C又继承了A,所以D中存放了两个A,这里就存在数据冗余,如果A中存在4G的数据,那么D中就存在8G的数据,此时D中就有两个A,虽然两个A名字一样,但是一个A是B的,一个A是C的,所以这两个A也不一样

struct A
    {
        int _a;
    };
    class B : public A
    {
    public:
        int _b;
    };
    class C :public A
    {
    public:
        int _c;
    };
    class D :public B, public C//D继承了B,C
    {
    public:
        int _d;
    };
bosthhe1 commented 1 year ago

所以为了解决菱形继承的问题,c++抛出了虚继承的概念

    struct A
    {
        int _a;
    };
    class B : virtual public A//虚继承A
    {
    public:
        int _b;
    };
    class C : virtual public A//虚继承A
    {
    public:
        int _c;
    };
    class D :public B, public C
    {
    public:
        int _d;
    };

需要注意的是,在初始化列表中,初始化的顺序是声明的顺序,在继承中先被继承的先声明,所以如果初始化D中,会先初始化A,由于A中是计算的偏移量,大家看到的都是同一个A,所以编译器会优化,A的初始化交给D,所以初始化会先A,再初始化B,再初始化C,最后初始化D 虚继承的原理是将B,C的位置,与A位置的偏移量,保存在一个内存空间中,B,C需要访问A,就需要通过计算与A的偏移量,因为是计算偏移量,所以B,C访问的A为同一个A(这里存在虚基表,访问A时需要查询虚基表)。 image

bosthhe1 commented 1 year ago

一般的继承都需要写继承方式,如果没有写继承方式,那么默认就是私有继承 class B:A//私有继承

bosthhe1 commented 1 year ago

image 补充,我们看到虚继承然后实现多态的情况下,在地址偏移量上面存在着一个地址很大的值,存的虚基表的偏移量,通过偏移量找到虚表指针,需要总结的是在菱形虚继承中,编译器都会将共有的部分提出来,以防止二义性,所以在菱形虚继承中将A提出来,然后存的偏移量,在菱形虚继承虚函数重写中,编译器会将A的虚表拿出来,然后计算虚表的偏移量

bosthhe1 commented 1 year ago

继承和组合的区别 image