IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++基础 虚继承 -> 正文阅读

[C++知识库]C++基础 虚继承

c++之中一个类不能被多次说明为一个派生类的直接基类,但可以多次成为间接基类。

一 非虚继承类

例子:

class B
{
    public:
    int x.....
}
class A1:public B
{
    .....
}
class A2:public B
{
    ......
}
class D:public A1,public A2
{
    ......
}

可以看出,D类继承了A1和A2,而A1和A2继承了B ,也就是说D类有两个B类的成员副本,所以称B是非虚基类。

非虚继承测试:

#include<iostream>
using namespace std;
class B
{
    public:
    B()
    {cout<<"construct called:B\n";}
    ~B()
    {cout<<"destructor called:B\n";}
    int b;
};
class B1:public B
{
    public:
    B1() {cout<<"constuct called:B1\n";}
    ~B1() {cout<<"destruct called:B1"<<endl;}
    int b1;
};
class B2:public B
{
    public:
    B2() {cout<<"constuct called:B2\n";}
    ~B2() {cout<<"destruct called:B2"<<endl;}
    int b2;    
};
class D:public B1,public B2
{
    public:
    D() {cout<<"constuct called:D\n";}
    ~D() {cout<<"destruct called:D"<<endl;}
    int d;
};
void test()
{
    D dd;
    dd.B1::b=5;
    dd.B2::b=10;
    dd.b1=25;
    dd.b2=111;
    dd.d=149;
    cout<<"dd.B1::b="<<dd.B1::b<<"dd.B2::b"<<dd.B2::b<<"dd.b1="<<dd.b1<<"dd.b2="<<dd.b2<<"dd.b"<<dd.d<<endl;
}
int main()
{
    test();
}

运行结果可以自己去试着运行看一下。

运行后第一轮输出的字符,如“construct called:B”等可以看出运行的顺序。

而void test()里面它直接用D dd,并且输出有d1,d2,d,b,而class D里只是定义了int d;所以显而易见是因为继承了B1和B2。还有要注意,为了访问不同版本的d,必须要用作用域指名是那个基类。

虚继承

当我们为了避免产生二义性,直接想用一个dd.b版本的时候,我们就需要把B1和B2对 B的继承说明为虚继承,它的说明形式是在类继承的关键字前面加一个virtual。这样就不用分别再建立dd.B1:: b,dd. B2::b,而是有virtual指引建立指向dd.b的指针。比如,让我们对上面的例子进行改动,利用virtual。

#include<iostream>
using namespace std;
class B
{
    public:
    B()
    {cout<<"construct called:B\n";}
    ~B()
    {cout<<"destructor called:B\n";}
    int b;
};
class B1:virtual public B
{
    public:
    B1() {cout<<"constuct called:B1\n";}
    ~B1() {cout<<"destruct called:B1"<<endl;}
    int b1;
};
class B2:virtual public B
{
    public:
    B2() {cout<<"constuct called:B2\n";}
    ~B2() {cout<<"destruct called:B2"<<endl;}
    int b2;    
};
class D:public B1,public B2
{
    public:
    D() {cout<<"constuct called:D\n";}
    ~D() {cout<<"destruct called:D"<<endl;}
    int d;
};
void test()
{
    D dd;
    dd.B1::b=5;
    dd.B2::b=10;
    dd.b1=25;
    dd.b2=111;
    dd.d=149;
    cout<<"dd.B1::b="<<dd.b<<"dd.B2::b"<<dd.b<<"dd.b1="<<dd.b1<<"dd.b2="<<dd.b2<<"dd.b"<<dd.d<<endl;//这里有改动
}
int main()
{
    test();
}

运行后我们会发现不会出翔二义性了,对象就只有一个b数据成员了。

最后说一句,一个类体系中可以作为虚继承和非虚继承取决于对他的继承方式,于基类本身的定义无关。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-10 10:52:59  更:2021-12-10 10:54:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 11:56:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码