• 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++类对象的内存结构……

     

  • 相关阅读:
    Java调用存储过程
    Eclipse快捷键
    [转载]实现GridView手动设定分页
    给博客换了个皮肤
    在Hibernate中使用Oracle的sequence主键
    解决Oracle 10g中The account lockde!
    [转载]CSS的优化与技巧
    PowerDesigner12 简单应用
    【转载】用开源软件搭建企业内部协作平台, Kill QQ MSN
    DropDownList数据绑定第一项为空
  • 原文地址:https://www.cnblogs.com/jdxn/p/12773219.html
Copyright © 2020-2023  润新知