继承

作者: 阿杜me | 来源:发表于2018-07-13 14:20 被阅读0次

    单继承
    class base
    {
    public:
    virtual void fun() {}
    protected:
    int var
    };

    base内存结构:
    0:vfptr -> base::fun
    4:var

    class A : public base
    {
    public:
    virtual void fun() {}
    virtual void funA() {}
    protected:
    int varA
    };

    A内存结构:
    0:vfptr -> A::fun A::funA
    4:var
    8:varA

    多重继承

    class B : public base
    {
    public:
    virtual void fun() {}
    virtual void funB() {}
    protected:
    int varB
    };

    class C : public A, public B
    {
    public:
    virtual void fun() {}
    virtual void funC() {}
    protected:
    int varC
    };

    C内存结构:
    0:vfptr -> A::fun A::funA C::funC
    4:var
    8:varA
    12:vfprt -> B::fun B::funB
    16:var
    20:varB
    24:varC

    虚拟继承

    class C : virtual public A, virtual public B
    {
    public:
    virtual void fun() {}
    virtual void funC() {}
    protected:
    int varC
    };

    C内存结构:
    0:vfptr -> A::funA C::funC
    4:vbprt -> -4 24
    8:varA
    12:vfprt -> B::funB
    16:vbptr -> -4 12
    20:varB
    24:varC
    28:vfprt -> C::fun
    32:var

    构造函数
    默认构造函数,两种情况,一是参数为空的构造函数、一个是参数都有默认值的构造函数

    构造函数指向顺序:虚基类(继承顺序) -> 直接父类(继承顺序) -> 自己类成员构造函数(声明顺序) -> 自己的构造函数

    如果无显示调用构造函数,则调用默认构造函数,如果没有默认构造函数,则编译器创建一个默认构造函数。

    析构函数
    与构造函数相反,虚构函数必须是虚函数,这样保证调用时从继承类开始执行,如果部署虚函数,有可能只调用基类析构函数,而没有析构继承类的

    拷贝构造函数
    无定义拷贝构造函数,则按构造函数调用顺序调用相应父类、类成员、自己的的默认拷贝构造函数
    有显示定义拷贝构造函数,则按构造函数调用顺序调用相应父类、类成员、自己的的默认构造函数(如果有显示初始父类,则调用相应的构造函数,无则调用默认构造函数)

    赋值操作符号重载
    如果有显示定义赋值操作符号,则不调用父类的,只执行自己的,对于父类部分操作需要专门代码处理
    如果没有显示定义赋值操作符号,则按构造函数执行顺序,先调用虚基类,直接父类,及自己的。

    多重继承的指针赋值:
    C objc;
    A pobja=&objc; //
    B pobjb=&objc; //编译器做了调整

    一般指针类型转换,都是不修改指针的值,只改变指针的类型(指针指向的内存的解释方式),多重继承下的指针转换会做调整。

    pobja 地址与 objc一致
    pobjb 地址与 objc不一致,差A长度

    assert(pobja == pobjb) 编译器做调整

    相关文章

      网友评论

          本文标题:继承

          本文链接:https://www.haomeiwen.com/subject/dgwjpftx.html