C++中的接口继承和实现继承
很多人认为,C++中是不存在接口继承的,只有Java、C#这类语言才提供了相应的语法支持。
但是,如同鲁迅说过的某句名言:世上本没有接口继承,用的人多了,才有了接口继承。C++中依然可以实现接口继承,只是形式上稍有不同罢了。
C++中的继承基于一个事实:父类定义的成员函数会一直被子类继承(包括被子类隐藏的部分)。
而父类中提供的函数可以有三种:1)普通成员函数 2)普通虚函数 3)纯虚函数。这三种函数类型代表了三种继承设计模式。
一个简单的实例代码如下:
01 |
class Shape |
02 |
{ |
03 |
public: |
04 |
virtual void Draw() = 0; |
05 |
virtual int GetError(); |
06 |
int GetId(); |
07 |
}; |
08 |
09 |
class Rectangular : public Shape |
10 |
{ |
11 |
//... |
12 |
}; |
13 |
14 |
class Circle : public Shape |
15 |
{ |
16 |
//... |
17 |
}; |
普通成员函数由父类声明且实现,子类应继承接口以及强制性的实现。
这几乎是最常见的一种函数类型,代表了典型的”is-a”继承设计模式。
ps:所谓的”is-a”设计模式,指的是”everything that applies to base classes must also apply to derived classes”
示例中,函数GetId严格遵守”is-a”模式。因为每个子类本质都是一个Shape对象,都有一个唯一的ID
普通虚函数可以在父类中有默认的实现,而这个默认实现可以由子类继承。
子类也可以选择重写虚函数以实现多态性。
所以,普通虚函数在继承设计中表示派生类必须支持此接口,但是否重写,由派生类自己决定。
如同每个子类对象都应该有一个报错函数。但是函数可以使用父类提供的默认实现(提示简单的出错信息,然后清理资源),也可以选择自己实现(每个子类有自己的错误语义)
纯虚函数会使得父类自动成为不可实例化的抽象类。而且每个继承的子类必须强制自行重写。
所以,纯虚函数表示子类继承父类的函数接口,并且必须自己具体实现该函数。
即从这个角度上看,纯虚函数代表的就是接口继承。
实例代码中,父类将Draw声明为纯虚函数。这表明每个具体的子类都应该有Draw函数,并且需要自己实现(每个具体子类的Draw实现应是不同的)。
对于纯虚函数,有一个有意思的特性:纯虚函数可以有实现代码
之所以说这个特性有意思,是因为拥有纯虚函数的类不能实例化并且纯虚函数指定的是接口继承,子类仍然需要自己实现函数。
这就引发了一个问题:如何调用这个纯虚函数的默认实现版本?解决的方法是显式调用
1 |
Shape* p = new Rectangular; |
2 |
assert(p != NULL); |
3 |
4 |
// invoke defaulat implementation of the pure-virtual function |
5 |
p->Shape::Draw(); |
6 |
7 |
// doing something later |
8 |
delete p; |
那么这种让人觉得操蛋的trick有没有什么应用呢?
假设你有一个父类F,定义了一个普通虚函数,子类A,B都使用默认的虚函数实现。但是某天你需要增加一个新的子类C,但是这个子类不能使用默认的实现,必须重写。
不幸的是,你忘了重写这个函数,所以编译器为你调用了默认实现,于是意外的结果让你蛋碎了一地。
很明显,使用带有实现的纯虚函数就可以解决这个问题。纯虚函数会强制要求你重写虚函数,而你也可以在需要默认实现时通过显式调用完成相应工作。
不过需要这种trick的情况相当罕见,而且多半是设计出了问题或者完全可以人为避免。
C++中的接口继承和实现继承的更多相关文章
- 第五节:详细讲解Java中的接口与继承
前言 大家好,给大家带来详细讲解Java中的接口与继承的概述,希望你们喜欢 什么是接口(interface) 接口中的方法都是抽象方法,public权限,全是抽象函数,不能生成对象 interface ...
- 【Java面试题】60 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法?
接口可以继承接口.抽象类可以实现(implements)接口,抽象类可以继承具体类.抽象类中可以有静态的main方法. 问: 抽象类是否可继承实体类 (concrete class) 答: 抽象类是 ...
- Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现
前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...
- Java中的集合(六)继承Collection的Set接口
Java中的集合(六)继承Collection的Set接口 一.Set接口的简介 Set接口和List接口都是继承自Collection接口,它与Collection接口中功能基本一致,并没有对Col ...
- Java中的集合(五)继承Collection的List接口
Java中的集合(五)继承Collection的List接口 一.List接口简介 List是有序的Collection的,此接口能够精确的控制每个元素插入的位置.用户能够根据索引(元素在List接口 ...
- Java中的集合(三)继承Collection的Queue接口
Java中的集合(三)继承Collection的Queue接口 一.Queue介绍 Queue接口继承自Collection接口,是Java中定义的一种队列数据结构,元素是有序的(按插入顺序排序),先 ...
- Effective C++ 34 区分接口继承和实现继承
public继承从根本上讲,有两部分:接口继承和实现继承.两者之前的区别很像函数声明与函数定义. 具体设计中,会呈现三种形式:derived class只继承成员函数的接口(纯虚函数):derived ...
- c++ 接口继承和实现继承
所谓接口继承,就是派生类只继承函数的接口,也就是声明:而实现继承,就是派生类同时继承函数的接口和实现. 我们都很清楚C++中有几个基本的概念,虚函数.纯虚函数.非虚函数. 虚函数: 虚函数是指一个类中 ...
- JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)
实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...
- pure virtual、impure virtual、non-virtual函数的接口继承和实现继承
1.abstract class 拥有pure virtual函数的class是abstract class. 不能创建abstract class的实体. 2.pure virtual 函数 他们必 ...
随机推荐
- POJ 2425 A Chess Game(有向图SG函数)题解
题意:给一个有向图,然后个m颗石头放在图上的几个点上,每次只能移动一步,如果不能移动者败 思路:dfs打表sg函数,然后求异或和 代码: #include<queue> #include& ...
- Java名称由来
2000年度的JavaOne国际会议大厅热闹非凡,一阵阵浓郁的咖啡味儿香气扑鼻.从世界各地汇集到旧金山参加会议的Java精英们兴奋异常,排着长队,等待得到一杯由Java语言控制的咖 ...
- 项目梳理7——Nuget包管理
1.添加Nuget源 nuget包管理.生成自己的nuget包.向 NuGet 添加更多程序包源 nuget的所有使用介绍 打包示例 .nuspec文件声明的是对应NuGet包的以下内容: 包更新命令 ...
- HDU 2089 不要62(数位dp模板题)
http://acm.hdu.edu.cn/showproblem.php?pid=2089 题意:求区间内不包含4和连续62的数的个数. 思路: 简单的数位dp模板题.给大家推荐一个好的讲解博客.h ...
- hibernate报错 java.lang.StackOverflowError: null
在使用hibernate时,报错 java.lang.StackOverflowError: null 把当前线程的栈打满了 java.lang.StackOverflowError: null at ...
- LINUX设备驱动模型之class
转自 https://blog.csdn.net/qq_20678703/article/details/52754661 1.LINUX设备驱动模型中的bus.device.driver,.其中bu ...
- POJ 1509 Glass Beads---最小表示法
题意: T组数据,每组数据给出一个字符串,求这个字符串的最小表示发(只要求输出起始位置坐标) SAM入门题(检测板子是否正确). 将字符串S加倍丢进SAM中,然后走字符串长度次,每次贪心的沿最小的边走 ...
- python 元组元素反转
#create a tuple x = ("w3resource") # Reversed the tuple y = reversed(x) print(tuple(y)) #c ...
- Springboot 学习笔记 之 Day 2
“约定大于配置”这样一句话,就是说系统,类库,框架应该假定合理的默认值,而非要求提供不必要的配置,可是使用Spring或者SpringMVC的话依然有许多这样的东西需要我们进行配置,这样不仅徒增工作量 ...
- API接口自动化之3 同一个war包中多个接口做自动化测试
同一个war包中多个接口做自动化测试 一个接口用一个测试类,每个测试用例如下,比如下面是4个测试用例,每个详细的测试用例中含有请求入参,返回体校验,以此来判断每条测试用例是否通过 一个war包中,若含 ...