温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

虚拟继承

发布时间:2020-06-06 05:29:34 来源:网络 阅读:387 作者:清幽宁 栏目:移动开发

在缺省情况下,C++中的继承是按值组合的一种特殊情况,比如:

class B :virtual  public A{ ... };

每个B类对象都含有其A基类子对象的所有非静态数据成员,以及在B中声明的非静态数据成员。类似地,当派生类自己也作为一个基类对象时,如:

class C :virtual  public B{ ... };

C 类对象含有在C中声明的所有非静态数据成员,以及其B子对象的所有非静态数据成员和A子对象的所有非静态数据成员。

在单继承下,这种由继承支持的.特殊形式的按值组合提供了最有效的,最紧凑的对象表示。在多继承下,当一个基类在派生层次中出现多次时就会有问题。 最主要的实际例子是

iostream 类层次结构,在下图 ostream istream 类都从抽象 ios 基类派生而来,而 iostream 类又是从 ostream istream 派生:

虚拟继承虚拟继承

class iostream :

         public istream , public ostream { ... };

缺省情况下,每个 iostream 类对象含有两个 ios 子对象:在 istream 子对象中的实例以及ostream 子对象中的实例。这为什么不好?从效率上而言,存储 ios 子对象的两个复本,浪费了存储区,因为 iostream 只需要一个实例。而且 ios 构造函数被调用了两次,每个子对象一次,更严重的问题是由于两个实例引起的二义性,例如:任何未限定修饰地访问 ios 成员都将导致编译时刻错误。到底访问哪个实例?如果 ostream istream 对其 ios 子对象的初始化稍稍不同,会怎样呢?怎样通过 iostream 类保证这一对 ios 值的一致性?在缺省的按值组合机制下,真的没有好办法可以保证这一点。

       C++语言的解决方案是,提供另一种可替代“按引用组合”的继承机制:虚拟继承。在虚拟继承下,只有一个共享的基类子对象被继承,而无论该基类在派生层次中出现多少次。共享的基类子对象被称为虚拟基类,在虚拟继承下,基类子对象的复制及由此而引起的二义性都被消除了。

C++中虚拟继承的概念

       为了解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。
class 派生类名:virtual 继承方式  基类名
virtual是关键字,声明该基类为派生类的虚基类。
在多继承情况下,虚基类关键字的作用范围和继承方式关键字相同,只对紧跟其后的基类起作用。

声明了虚基类之后,虚基类在进一步派生过程中始终和派生类一起,维护同一个基类子对象的拷贝。

C++虚拟继承

◇概念:

C++使用虚拟继承(Virtual Inheritance),解决从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。这时从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。

◇解决问题:

解决了二义性问题,也节省了内存,避免了数据不一致的问题。

◇二义性: 

#include "stdafx.h"

#include <iostream>

using namespace std;

 //Base

 class Base

 {

      public:

                Base(){ cout << "Base called..." << endl; }

                 void print(){ cout << "Base print..." << endl; }

                 private:

                        };


//Sub

class Sub //定义一个类 Sub

{

         public:

                Sub(){ cout << "Sub called..." << endl; }

                 void print(){ cout << "Sub print..." << endl; }

                 private:

                        };


//Child

class Child : public Base, public Sub //定义一个类Child 分别继承自 Base ,Sub

{

         public:

                Child(){ cout << "Child called..." << endl; }

                 private:

                        };

int main(int argc, char* argv [])

{

         Child c;

        

         //不能这样使用,会产生二意性,VC下error C2385

                 //c.print(); 

                 //只能这样使用

                c. Base::print();

        c. Sub::print();

        

        system( "pause");

         return 0;

        }


向AI问一下细节
推荐阅读:
  1. 继承&派生
  2. JS继承

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI