C++入门经典-例8.8-虚继承
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-虚继承的更多相关文章
- C++入门经典-例8.6-多重继承的构造顺序
1:单一继承是先调用基类的构造函数,然后调用派生类的构造函数,但多重继承将如何调用构造函数呢?多重继承中的基类构造函数被调用的顺序以派生表中声明的顺序为准.派生表就是多重继承定义中继承方式后面的内容, ...
- C++入门经典-例8.5-多重继承
1:C++允许子类从多个父类继承公有的和受保护的成员,这称为多重继承. 2:多重继承的定义.多重继承有多个基类名称标识符,其声明形式如下: class 派生类名标识符:[继承方式] 基类名标识符1,. ...
- C++入门经典-例8.1-类的继承
1:继承是面向对象的主要特征(此外还有封装和多态)之一,它使得一个类可以从现有类中派生,而不必重新定义一个新类.继承的实质就是用已有的数据类型创建新的数据类型,并保留已有数据类型的特点,以旧类为基础创 ...
- C++入门经典-例8.9-抽象类,纯虚函数,创建纯虚函数
1:包含有纯虚函数的类称为抽象类,一个抽象类至少具有一个纯虚函数.抽象类只能作为基类派生出的新的子类,而不能在程序中被实例化(即不能说明抽象类的对象),但是可以使用指向抽象类的指针.在程序开发过程中并 ...
- C++入门经典-例8.7-多态,利用虚函数实现动态绑定
1:多态性是面向对象程序设计的一个重要特征,利用多态性可以设计和实现一个易于扩展的系统.在C++语言中,多态是指具有不同功能的函数可以用同一个函数名,这样就可以用一个函数名调用不同内容的函数,发出同样 ...
- Java+7入门经典 - 6 扩展类与继承 Part 1/2
第6章 扩展类与继承 面向对象编程的一个重要特性: 允许基于已定义的类创建新的类; 6.1 使用已有的类 派生 derivation, 派生类 derived class, 直接子类 direct s ...
- Java+7入门经典 - 6 扩展类与继承 Part 2/2
6.12 设计类 1) 通过已定义的基类派生子类, 并且添加方法和数据成员来自定义子类, 创建出类的层次结构; Dog 'IS-A' Animal 2) 定义一系列没有层次结构, 由类对象作为数据成员 ...
- C++入门经典-例8.10-实现抽象类中的成员函数
1:抽象类通常作为其他类的父类,如果从抽象类派生的子类是抽象类,则子类必须实现父类中的所有纯虚函数.代码如下: // 8.10.cpp : 定义控制台应用程序的入口点. // #include &qu ...
- C++入门经典-例8.2-构造函数的访问顺序
1:父类和子类中都有构造函数和析构函数,那么子类对象在创建时是父类先进行构造还是子类先进行构造?同样,在子类对象释放时,是父类先进行释放,还是子类先进行释放?这都是有先后顺序的.答案是当从父类派生一个 ...
随机推荐
- NSIS逻辑函数头文件介绍
!include "LogicLib.nsh"使用 NSIS 的宏来提供各种逻辑基本语句,不需要预先添加函数. 基本语句 If|Unless..{ElseIf|ElseUnless ...
- java 计算中位数方法
最近工作需要 要求把python的代码写成java版本,python中有一个np.median()求中位数的方法,java决定手写一个 先说说什么是中位数: 中位数就是中间的那个数, 如果一个集合是奇 ...
- js数据类型的转换
类型转换:就是把一种数据类型转换成另一种数据类型,在js中类型转换有以下三种情况:转数字,转字符串,转布尔值.对象转成这3种数据类型是没有意义的,对象里面可以放任意的数据类型. 在讲解类型转换之前,先 ...
- Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))
转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用1.1. ReentrantLock ...
- Troubleshooting: Cannot Run on an Android Device
同事在他的开发环境中,在IDE中直接在手机上运行Android项目,结果出现这个错误,无法在手机上安装. 产生这个问题的原因,一般就是签名不对,这种情况,删除手机上装过的同名应用,就可以解决.当然,你 ...
- 第三章·Logstash入门-部署与测试
1.Logstash环境准备与安装 Logstash环境准备 关闭防火墙 #CentOS6 关闭防火墙 [root@elkstack01 ~]# /etc/init.d/iptables stop # ...
- 08-【jsp重点】
jsp的四个作用域和9个内置对象 jsp内置对象[重点]:pageContext.request.session.application.response.out.page.exception.con ...
- ELK对nginx日志进行流量监控
ELK对nginx日志进行流量监控 一.前言 线上有一套ELK单机版,版本为5.2.1.现在想把nginx访问日志接入到elk里,进行各个域名使用流量带宽的统计分析.要把nginx日志传输到elk上, ...
- Linux根文件系统和目录结构及bash特性4
文件管理工具:cp,mv,rm cp命令:copy cp命令主要用于复制文件或目录 语法: 单源复制 cp [OPTION]... [- ...
- 小程序UI设计(8)-布局分解-FlexBox的align-content应用
FlexBox的align-content到底是什么鬼,我也搞了好半天才开发出来,目前工具中WViewRow组件使用了此属性,WViewColumn中此属性不起作用.下图是justify-conten ...