• C++继承汇总(单继承、多继承、虚继承、菱形继承)


    一、C++中的对象模型

    1、 概念

    语言中直接支持面向对象程序设计的部分;

    对于各种支持的底层实现机制。(没看懂……)

    2、 类中的成员分类

    a) 成员函数

      i. static function

      ii. non static function

      iii. virtual function

    b)  数据成员

      i. static member data

      ii. non static member data

    3、 C++对象模型

    a) 类对象内存布局中的包括

      i. non static member data

      ii. vptr(虚函数表指针)

      iii. vbptr(虚基类表指针)

    b) 不包括

      i. static member data(存储在静态存储区)

      ii. 成员函数(存储在代码区)

    c) virtual table

    简称vtbl。存放着指针,这些指针指向该类每一个虚函数。虚表中的函数地址将按声明时的顺序排列。vtbl在类声明后就形成了,vptr是编译器生成的。

    d) vptr的位置一般放在一个类对象的最前端。

    e) 虚基类表

    vbptr指向的表,用于存放虚继承中,虚基类存储相对于虚基类表指针的偏移量。

    二、继承类型

    1、普通继承(不包含虚函数)

    a、单继承

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        void fun0(){cout << base << endl;}
        int base;
    };
    class Derive:public Base
    {
    public:
        Derive (int a = 2):derive(a){}
        void fun1(){cout << base1 << endl;}
        int derive;
    };

    b、多继承

    class Base1
    {
    public:
        Base1 (int a = 2):base1(a){}
        void fun1(){cout << base1 << endl;}
        int base1;
    };
    class Base2
    {
    public:
        Base2 (int a = 3):base2(a){}
        void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive: public Base1, public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        void fun3(){cout << derive << endl;}
        int derive;
    };

    c、菱形继承

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:public Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        void fun1(){cout << base1 << endl;}
        int base1;
    };
    class Base2:public Base
    {
    public:
        Base2 (int a = 3):base2(a){}
        void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive: public Base1, public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        void fun3(){cout << derive << endl;}
        int derive;
    };

    注:菱形继承存在二义性问题,编译都不通过,只能通过指定特定基类的方式进行访问基类变量。

    Derive d;

           d.base =3; // 不正确

           d.Base1::base = 3; // 正确

    2、普通继承(包含虚函数)

      a、单继承(包含虚函数)

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        virtual void fun0(){cout << base << endl;}
        int base;
    };
    class Derive:public Base
    {
    public:
        Derive (int a = 2):derive(a){}
        virtual void fun0(){};
        virtual void fun1(){cout << derive << endl;}
        int derive;
    };

    注:派生类中新增的虚函数追加到虚函数表后面。

    b、多继承(包含虚函数)

    class Base1
    {
    public:
        Base1 (int a = 2):base1(a){}
        virtual void fun1(){cout << base1 << endl;}
        int base1;
    };
    class Base2
    {
    public:
        Base2 (int a = 3):base2(a){}
        virtual void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive: public Base1, public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        virtual void fun3(){cout << derive << endl;}
        int derive;
    };

    注:派生类中新增的虚函数,追加到第一个基类的虚函数表的后面。

           c、菱形继承(包含虚函数)

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        virtual void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:public Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        virtual void fun1(){cout << base1 << endl;}
        int base1;
    };
    class Base2:public Base
    {
    public:
        Base2 (int a = 3):base2(a){}
        virtual void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive: public Base1, public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        virtual void fun3(){cout << derive << endl;}
        int derive;
    };

    注:分析时,由上到下依次分析。存在二义性问题和内存冗余问题。

     3、虚继承(不包含虚函数)

    新增虚基类指针,指向虚基类表,虚基类表中首项存储虚基类指针的偏移量,接下来依次存储虚基类的偏移量(偏移量是相对于虚基类表指针的存储地址)。

       a、单虚继承(不包含虚函数)

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:virtual public Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        void fun1(){cout << base1 << endl;}
        int base1;
    };

       b、多虚继承(不包含虚函数)

    class Base1
    {
    public:
        Base1 (int a = 2):base1(a){}
        void fun1(){cout << base1 << endl;}
        int base1;
    };
    class Base2
    {
    public:
        Base2 (int a = 3):base2(a){}
        void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive:virtual public Base1, virtual public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        void fun3(){cout << derive << endl;}
        int derive;
    };

      c、菱形虚继承(不包含虚函数)

       第一种形式:

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:virtual Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        void fun1(){cout << base1 << endl;}
        int base1;
    };
    class Base2:virtual Base
    {
    public:
        Base2 (int a = 3):base2(a){}
        void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive:virtual public Base1, virtual public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        void fun3(){cout << derive << endl;}
        int derive;
    };

    注:分析派生类的内存分布时,也是由上到下分析。虚继承将基类置于内存末尾,但是置于末尾的顺序也有一定的次序。首先Base先放到末尾,然后Base1放到末尾,最后Base2放到末尾。

           第二种形式:

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:virtual public Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        void fun1(){cout << base1 << endl;}
        int base1;
    };
    
    class Base2:virtual public Base
    {
    public:
        Base2 (int a = 3):base2(a){}
        void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive: public Base1, public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        void fun3(){cout << derive << endl;}
        int derive;
    };

    注:分析的原则,从上到下,依次分析。

    4、 虚继承(包含虚函数)

    a、单虚继承(包含虚函数)

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        virtual void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:virtual Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        virtual void fun1(){cout << base1 << endl;}
        int base1;
    };

      与普通的包含虚函数的单继承相比,派生类拥有自己的虚函数表以及虚函数表指针,而不是与基类共用一个虚函数表。注意虚函数表指针和虚基类表指针的存储顺序。

      b、多虚继承(包含虚函数)

    class Base1
    {
    public:
        Base1 (int a = 2):base1(a){}
        virtual void fun1(){cout << base1 << endl;}
        int base1;
    };
    
    class Base2
    {
    public:
        Base2 (int a = 3):base2(a){}
        virtual void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive:virtual public Base1, virtual public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        virtual void fun3(){cout << derive << endl;}
        int derive;
    };

    c、菱形虚继承(包含虚函数)

           第一种形式:

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        virtual void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:virtual public Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        virtual void fun1(){cout << base1 << endl;}
        int base1;
    };
    
    class Base2:virtual public Base
    {
    public:
        Base2 (int a = 3):base2(a){}
        virtual void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive:  public Base1, public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        virtual void fun3(){cout << derive << endl;}
        int derive;
    };

    第二种形式:

    class Base
    {
    public:
        Base (int a = 1):base(a){}
        virtual void fun0(){cout << base << endl;}
        int base;
    };
    class Base1:virtual public Base
    {
    public:
        Base1 (int a = 2):base1(a){}
        virtual void fun1(){cout << base1 << endl;}
        int base1;
    };
    
    class Base2:virtual public Base
    {
    public:
        Base2 (int a = 3):base2(a){}
        virtual void fun2(){cout << base2 << endl;}
        int base2;
    };
    class Derive: virtual public Base1,virtual public Base2
    {
    public:
        Derive (int value = 4):derive (value){}
        virtual void fun3(){cout << derive << endl;}
        int derive;
    };

    自行脑补C++类对象的内存结构……

    注:上述虚函数中,如果派生类重写了基类的虚函数,则对应虚函数表中的虚函数应该修改成重新后的虚函数,即Base::fun()->Derive::fun()。

    参考链接:

      http://www.cnblogs.com/raichen/p/5744300.html

  • 相关阅读:
    Hibernate中使用@Lob 注解保存String[] 问题
    具体解释Java虚拟机类载入
    POJ 2631 Roads in the North(树的直径)
    MySQL远程訪问的两个问题
    org.hibernate.LazyInitializationException could not initialize proxy-no Session的解决
    博客搬家啦!
    hdu 5015 233 Matrix (矩阵高速幂)
    Flink内存管理源代码解读之基础数据结构
    UML图与机房收费系统实例
    TextView设置成仅仅读
  • 原文地址:https://www.cnblogs.com/longcnblogs/p/7642951.html
Copyright © 2020-2023  润新知