1:以前讲到从CBird类和CFish类派生子类CWaterBird时,在CWaterBird类中将存在两个CAnimal类的复制。那么如何在派生CWaterBird类时使其只存在一个CAnimal基类呢?C++语言提供的虚继承机制能够解决这个问题。

代码如下:

// 8.8.cpp : 定义控制台应用程序的入口点。
// #include "stdafx.h"
#include <iostream>
using namespace std;
class CAnimal //定义一个动物类
{
public:
CAnimal() //定义构造函数
{
cout << "动物类被构造"<< endl; //输出信息
}
void Move() //定义成员函数
{
cout << "动物能够移动"<< endl; //输出信息
}
};
class CBird : virtual public CAnimal //从CAnimal类虚继承CBird类
{
public:
CBird() //定义构造函数
{
cout << "鸟类被构造"<< endl; //输出信息
}
void FlyInSky() //定义成员函数
{
cout << "鸟能够在天空飞翔"<< endl; //输出信息
}
void Breath() //定义成员函数
{
cout << "鸟能够呼吸"<< endl; //输出信息
}
};
class CFish: virtual public CAnimal //从CAnimal类虚继承CFish
{
public:
CFish() //定义构造函数
{
cout << "鱼类被构造"<< endl; //输出信息
}
void SwimInWater() //定义成员函数
{
cout << "鱼能够在水里游"<< endl; //输出信息
}
void Breath() //定义成员函数
{
cout << "鱼能够呼吸"<< endl; //输出信息
}
};
class CWaterBird: public CBird, public CFish //从CBird和CFish类派生子类CWaterBird
{
public:
CWaterBird() //定义构造函数
{
cout << "水鸟类被构造"<< endl; //输出信息
}
void Action() //定义成员函数
{
cout << "水鸟既能飞又能游"<< endl; //输出信息
}
};
int main(int argc, char* argv[]) //主函数
{
CWaterBird waterbird; //定义水鸟对象
return ;
}

运行结果:

上述代码中,在定义CBird类和CFish类时使用了关键字virtual,CFish类从基类CAnimal派生而来。实际上,虚继承对CBird类和CFish类没有多少影响,却对CWaterBird类产生了很大的影响。CWaterBird类中不再有两个CAnimal类的复制,而只存在一个CAnimal的复制。

通常,在定义一个对象时,先依次调用基类的构造函数,最后才调用自身的构造函数。但是对于虚继承来说情况有些不同。在定义CWaterBird类的对象时,先调用基类CAnimal的构造函数,然后调用CBird类的构造函数,这里CBird类虽然为CAnimal的子类,但是在调用CBird类的构造函数时将不再调用CAnimal类的构造函数。对于CFish也是同样的道理。

C++入门经典-例8.8-虚继承的更多相关文章

  1. C++入门经典-例8.6-多重继承的构造顺序

    1:单一继承是先调用基类的构造函数,然后调用派生类的构造函数,但多重继承将如何调用构造函数呢?多重继承中的基类构造函数被调用的顺序以派生表中声明的顺序为准.派生表就是多重继承定义中继承方式后面的内容, ...

  2. C++入门经典-例8.5-多重继承

    1:C++允许子类从多个父类继承公有的和受保护的成员,这称为多重继承. 2:多重继承的定义.多重继承有多个基类名称标识符,其声明形式如下: class 派生类名标识符:[继承方式] 基类名标识符1,. ...

  3. C++入门经典-例8.1-类的继承

    1:继承是面向对象的主要特征(此外还有封装和多态)之一,它使得一个类可以从现有类中派生,而不必重新定义一个新类.继承的实质就是用已有的数据类型创建新的数据类型,并保留已有数据类型的特点,以旧类为基础创 ...

  4. C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数

    1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并 ...

  5. C++入门经典-例8.7-多态,利用虚函数实现动态绑定

    1:多态性是面向对象程序设计的一个重要特征,利用多态性可以设计和实现一个易于扩展的系统.在C++语言中,多态是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数,发出同样 ...

  6. Java+7入门经典 - 6 扩展类与继承 Part 1/2

    第6章 扩展类与继承 面向对象编程的一个重要特性: 允许基于已定义的类创建新的类; 6.1 使用已有的类 派生 derivation, 派生类 derived class, 直接子类 direct s ...

  7. Java+7入门经典 - 6 扩展类与继承 Part 2/2

    6.12 设计类 1) 通过已定义的基类派生子类, 并且添加方法和数据成员来自定义子类, 创建出类的层次结构; Dog 'IS-A' Animal 2) 定义一系列没有层次结构, 由类对象作为数据成员 ...

  8. C++入门经典-例8.10-实现抽象类中的成员函数

    1:抽象类通常作为其他类的父类,如果从抽象类派生的子类是抽象类,则子类必须实现父类中的所有纯虚函数.代码如下: // 8.10.cpp : 定义控制台应用程序的入口点. // #include &qu ...

  9. C++入门经典-例8.2-构造函数的访问顺序

    1:父类和子类中都有构造函数和析构函数,那么子类对象在创建时是父类先进行构造还是子类先进行构造?同样,在子类对象释放时,是父类先进行释放,还是子类先进行释放?这都是有先后顺序的.答案是当从父类派生一个 ...

随机推荐

  1. QT之QString的arg方法

    转载.标记一下,总结的很好 转自 http://www.cnblogs.com/lomper/p/4135387.html 在QT的QString中,arg方法类似于C中的printf中使用的格式输出 ...

  2. Ubuntu12.04+Caffe (+OpenCV+CPU-only)

    经过一天的努力发现12.04 的pcre的库太低了,   要解决这个bug只能升级系统到16.04   麻蛋!!! 1.  下载大神MTCNN 源码,内含caffe https://github.co ...

  3. Spring中常用的设计模式之:代理模式

    看了tom老师讲的深入分析spring源码,讲的挺好,做个小总结 代理模式的定义: 为其他对象提供一种代理以控制对这个对象的访问.在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以 ...

  4. git、github常用操作

    1.将github项目拷贝到本地 $ git clone https://github.com/jim2500/miaosha_project.git 2.修改本地项目上传到github T470s@ ...

  5. TensorFlow教程使用RNN生成唐诗

    本教程转载至:TensorFlow练习7: 基于RNN生成古诗词 使用的数据集是全唐诗,首先提供一下数据集的下载链接:https://pan.baidu.com/s/13pNWfffr5HSN79WN ...

  6. Java高并发程序设计学习笔记(十一):Jetty分析

    转自:https://blog.csdn.net/dataiyangu/article/details/87894253 new Server()初始化线程池QueuedThreadPoolexecu ...

  7. 1、CentOs安装

    转载自:代码之美 0.准备工作: 一台没系统的普通电脑u盘一个(大于1G,最小安装的话不超过1G,根据选择系统大小匹配U盘即可)CentOS7.3 iso文件一个UltraISO工具 1.制作U盘 ① ...

  8. MongoDB 各个位版本下载地址

    官网首页下载需要填写资料 windows版本 Linux版本

  9. IIS出现Server Error in '/' Application 错误的解决办法

    C:\Windows\Temp"文件夹加上 IIS_IUSRS的权限

  10. 02-【servlet】

    1.什么是Servlet Servlet是JavaWeb的三大组件之一[Servlet,Filter,Listener],它属于动态资源.Servlet的作用是处理请求,服务器会把接收到的请求交给Se ...