虚继承 订阅
虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如下图所示。类D继承自类B1、B2,而类B1、B2都继承自类A,因此出现如右图所示的局面(非虚基类)。 展开全文
虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如下图所示。类D继承自类B1、B2,而类B1、B2都继承自类A,因此出现如右图所示的局面(非虚基类)。
信息
属    于
面向对象编程中的一种技术
包    含
多重继承中特有的概念
含    义
指定的基类,在继承体系结构中
中文名
虚继承
虚继承基本概述
虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如下图所示。类D继承自类B1、B2,而类B1、B2都继承自类A,因此出现如右图所示的局面(非虚基类)。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。最后形成如左图所示的情况。实现的代码如下: class A;class B1:public virtual A;class B2:public virtual A;class D:public B1,public B2;
收起全文
精华内容
下载资源
问答
  • 虚继承

    2018-04-26 10:51:03
    虚继承的必要性 解决菱形继承带来的数据冗余和二义性。由于B 和C都继承了类A,那么B和C中就各有一份A的内容,而D又分别继承了B和C,那么D中就有两份a,造成了数据冗余,而且在访问_a成员时,就会有二义性的产生,...

    虚继承的必要性

    这里写图片描述
    解决菱形继承带来的数据冗余和二义性。由于B 和C都继承了类A,那么B和C中就各有一份A的内容,而D又分别继承了B和C,那么D中就有两份a,造成了数据冗余,而且在访问_a成员时,就会有二义性的产生,指向不明。所以为了解决这种问题引出了虚继承

    什么是虚继承

    虚继承就是在B和C在继承A时加上关键字virtual就是虚继承了,

    #include<iostream>
    using namespace std;
    class A{
    public:
        int _a;
    };
    class B :virtual public A{
    public:
        int _b;
    };
    class C :virtual public A{
    public:
        int _c;
    };
    class D :public B,public C{
    public:
        int _d;
    };
    int main(){
        D d;
        d._a=1;
        d._b = 2;
        d._c = 3;
        d._d = 4;
        cout<<sizeof(d)<<endl;//   20  //虚继承后大小变为24
        system("pause");
        return 0;
    }

    为什么虚继承后D的大小反而变量大了,这岂不是不能达到解决数据冗余的效果了?
    这里写图片描述,按照结果来看是不是觉得并没有达到解决数据冗余的问题,这是因为A中的数据少,如果A中的成员很多,空间很大,那么两个指针的作用就很大了,可以省略很多空间的开销。

    展开全文
  • 虚函数继承与虚继承

    2019-09-03 11:09:35
    虚函数继承和虚继承是完全不同的两个概念。 虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联。 虚继承就是为了节约...

    虚函数继承和虚继承是完全不同的两个概念。

    虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联。

    虚继承就是为了节约内存,他是多重继承中的特有的概念。适用于菱形继承形式。

    比如B继承于A、C继承于A、D继承于B和C,显然D会继承两次A(图1)。因此,为了节省空间,可以将B、C对A的继承定义为虚拟继承,而A就成了虚拟基类(图2)。代码如下:

     A    A           A 
      \    /           / \ 
      B   C           B  C 
       \  /            \  / 
       D             D 
      (图1)          (图2)

    class A; 
    class B:vitual public A; 
    class C:vitual public A; 
    class D:public B,public C; 


    虚继承的时候子类会有一个指向自己虚函数表的指针,同时也会加入一个指向父类的虚类指针,然后还要包含父类的所有内容。

    虚继承时如果子类父类都有虚函数,那么它会重新建立一张虚表,不包含父类虚表的内容;而在普通的继承中却是在父类虚表的基础上建立一张虚表。这就意味着如果虚继承中子类父类都有各自的虚函数,在子类里面就会有两个虚函数表指针,一个指向父类的虚表,一个指向子类的虚表,而普通的继承只有一个指向子类虚表的指针。代码说明:

    class A
    {
        int k;
    public:
        virtual void aa(){};
    };
    
    class B:public virtual A
    {
        int j;
    public:
        virtual void bb(){};
    };
    
    class C:public virtual B
    {
        int i;
    public:
        virtual void cc(){};
    };
    
    int main()
    {
        cout << sizeof(A) << endl;
        cout << sizeof(B) << endl;
        cout << sizeof(C) << endl;
        system("pause");
        return 0;
    }

    输出结果为:8、20、32。

    怎么来的呢?类A中包含一个整型变量k(4字节),一个虚表指针(4字节),所以一共8字节。类B中,一个整型变量j(4字节),一个虚表指针(4字节),因为B虚继承于A,所有会有一个指向类A的虚类指针(4字节),同时还要包含类A中的整型变量k(4字节)以及类A的虚表指针(4字节),所以一共20字节。类C同理。

    如果将上述代码改为普通继承,那么输出结果为:8、12、16。没有虚类指针,也不会有多个虚表指针。

    展开全文
  • 继承和虚继承

    2021-02-12 20:45:13
    继承与虚继承 因为C++支持多重继承,那么在这种情况下会出现重复使用基类这种情况,也就是说可能出现将一个类两次作为基类的可能性。比如下面的情况: 为了节省空间,可以将DeriverdA和DeriverdB对Base的继承...

    继承与虚继承

    1. 因为C++支持多重继承,那么在这种情况下会出现重复使用基类这种情况,也就是说可能出现将一个类两次作为基类的可能性。比如下面的情况:
      在这里插入图片描述

    2. 为了节省空间,可以将DeriverdA和DeriverdB对Base的继承定义为虚拟继承,而Base就成了虚拟基类。

    class Base;
    class DeriverdA:public virtual Base;//虚继承
    class DeriverdB:public virtual Base;//虚继承
    class Son:public DeriverdA.DeriverdB;//普通继承
    
    1. 虚拟继承在一般的应用中很少遇到,所以往往被忽视,这也是因为在C++中,多重继承是不推荐的,也并不常用,而一旦离开了多继承,虚继承就完全失去了存在的必要性,因为这种情况下使用虚继承只会降低效率和占用更多的空间。
    2. 不要全部使用虚继承,因为虚继承会破坏继承体系,不能按照平常的继承体系来进行类型转换(如C++提供的强类型转换static_cast对继承体系中的类对象转换一般可行,但在这里就不行了)。所以不要轻易使用虚继承,更不要在虚继承的基础上进行类型转换!!!
    展开全文
  • 虚继承与虚函数继承

    2018-09-24 09:26:47
    虚继承主要用于菱形 形式的继承形式 虚继承是为了在多继承的时候避免引发歧义, 比如类A有个就是a,B继承了A,C也继承了A,当D多继承B,C时,就会有歧义产生了,所以要使用虚拟继承避免重复拷贝。 虚函数继承...

    虚函数继承就是覆盖。即基类中的虚函数被派生类中的同名函数所覆盖。

    转载:http://blog.sina.com.cn/s/blog_6ab0b9a80101boej.html

    虚继承主要用于菱形 形式的继承形式

    虚继承是为了在多继承的时候避免引发歧义,
    比如类A有个就是a,B继承了A,C也继承了A,当D多继承B,C时,就会有歧义产生了,所以要使用虚拟继承避免重复拷贝。
    虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联

    虚函数继承:
    class A
    {
    virtual void fun() {cout < <‘A’ <
    };

    class B : public A
    {
    virtual void fun() {cout < <‘B’ <
    };

    int main(int argv, char** argc)
    {
    A* p = new B;
    p->fun(); //结果输出B,而不是A,至于实现原理,其实是对象头部多了四个字节,它是一个指向虚函数表的地址指针,程序运行时通过这个表,找到了这个B::fun()的入口地址
    return 0;
    }

    通俗的讲,虚继承就是为了节约内存的,他是多重继承中的特有的概念。适用与菱形继承形式。
    如:类B、C都继承类A,D继承类B和C。为了节省内存空间,可以将B、C对A的继承定义为虚拟继承,此时A就成了虚拟基类。
    class A;
    class B:vitual public A;
    class C:vitual public A;
    class D:public B,public C;

    虚函数继承就是覆盖。即基类中的虚函数被派生类中的同名函数所覆盖。
    class parent
    {
    public:
    vitual void foo(){cout < <“foo from parent”;};
    void foo1(){cout < <“foo1 from parent”;};
    };
    class son:public parent
    {
    void foo(){cout < <“foo from son”;};
    void foo1(){cout < <“foo1 from son”;};
    };
    int main()
    {
    parent *p=new son();
    p->foo();
    p->foo1();
    return 0;
    }

    其输出结果是:
    foo from son,foo1 from parent

    1、真正意义上的虚函数调用,是运行时绑定的;
    2、什么是真正意义上的虚函数调用?通过指针或者引用执行虚函数;
    3、通过对象执行虚函数会不会是动态绑定的?不会。
    4、一个类是否有虚函数,就看它是否包含一个指向虚函数表的指针;
    5、如果类本身含有virtual 声明的函数,或者继承了virtual 函数,那么它肯定会包含一个指向虚函数表的指针;
    6、从纯抽象类或者非抽象类继承了virutal,意义上是一样的,效率上是一样的,并不因为你是纯抽象类的继承而效率变高;
    7、虚函数调用比普通函数调用慢多少?假设这个函数仅执行 return i > j,大概慢 15%左右(3000万 * 100次规模测试),如果是个真正有意义上的函数,效率影响可以忽略不计;
    8、因此说虚函数慢的基本上是放屁,担心虚函数影响效率的基本上是杞人忧天;
    9、虚函数会慢,但是那是对内联函数而言的,虚函数会忽略 inline前缀,请注意这一点;
    10、继承层次不影响虚函数效率,如果你这个类是原始类的第10层继承,那么虚函数调用效率和第1层继承的类没有差别,当然如果你要在该函数中调用上一层的虚函数那就另当别论了;
    11、每个类应该只有一个virtual table,而不是每个对象有一个(对象只含有指向虚表的指针),那些说虚函数增大空间开销的可以自宫了;
    12、如果一个类含有虚函数,在构造时,使用memset(this, 0, sizeof(*this))是找死的行为;
    13、虚函数是运行时多态,模板是编译时多态,一个动,一个是静。

    14、子类覆盖父类的虚函数的时候,实际上是在构造函数中修改了虚表中的函数指针;因此使得 FatherClass* p = new ChildClass();的情况下,p->VirtualFunc()始终执行的是子类的虚函数;

    展开全文
  • 虚函数继承和虚继承是完全不同的两个概念。 虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也叫动态编联。 虚继承就是为了节约...
  • 虚函数:用来解决动态多态的问题...虚函数继承和虚继承是完全不同的两个概念。虚函数继承是解决多态性的,当用基类指针指向派生类对象的时候,基类指针调用虚函数的时候会自动调用派生类的虚函数,这就是多态性,也...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,713
精华内容 6,685
关键字:

虚继承