很多人认为,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++中的接口继承和实现继承的更多相关文章

  1. 第五节:详细讲解Java中的接口与继承

    前言 大家好,给大家带来详细讲解Java中的接口与继承的概述,希望你们喜欢 什么是接口(interface) 接口中的方法都是抽象方法,public权限,全是抽象函数,不能生成对象 interface ...

  2. 【Java面试题】60 接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承具体类(concrete class)? 抽象类中是否可以有静态的main方法?

    接口可以继承接口.抽象类可以实现(implements)接口,抽象类可以继承具体类.抽象类中可以有静态的main方法. 问:  抽象类是否可继承实体类 (concrete class) 答: 抽象类是 ...

  3. Golang 中的 面向对象: 方法, 类, 方法继承, 接口, 多态的简单描述与实现

    前言: Golang 相似与C语言, 基础语法与C基本一致,除了广受争议的 左花括号 必须与代码同行的问题, 别的基本差不多; 学会了C, 基本上万变不离其宗, 现在的高级语言身上都能看到C的影子; ...

  4. Java中的集合(六)继承Collection的Set接口

    Java中的集合(六)继承Collection的Set接口 一.Set接口的简介 Set接口和List接口都是继承自Collection接口,它与Collection接口中功能基本一致,并没有对Col ...

  5. Java中的集合(五)继承Collection的List接口

    Java中的集合(五)继承Collection的List接口 一.List接口简介 List是有序的Collection的,此接口能够精确的控制每个元素插入的位置.用户能够根据索引(元素在List接口 ...

  6. Java中的集合(三)继承Collection的Queue接口

    Java中的集合(三)继承Collection的Queue接口 一.Queue介绍 Queue接口继承自Collection接口,是Java中定义的一种队列数据结构,元素是有序的(按插入顺序排序),先 ...

  7. Effective C++ 34 区分接口继承和实现继承

    public继承从根本上讲,有两部分:接口继承和实现继承.两者之前的区别很像函数声明与函数定义. 具体设计中,会呈现三种形式:derived class只继承成员函数的接口(纯虚函数):derived ...

  8. c++ 接口继承和实现继承

    所谓接口继承,就是派生类只继承函数的接口,也就是声明:而实现继承,就是派生类同时继承函数的接口和实现. 我们都很清楚C++中有几个基本的概念,虚函数.纯虚函数.非虚函数. 虚函数: 虚函数是指一个类中 ...

  9. JAVA与多线程开发(线程基础、继承Thread类来定义自己的线程、实现Runnable接口来解决单继承局限性、控制多线程程并发)

    实现线程并发有两种方式:1)继承Thread类:2)实现Runnable接口. 线程基础 1)程序.进程.线程:并行.并发. 2)线程生命周期:创建状态(new一个线程对象).就绪状态(调用该对象的s ...

  10. pure virtual、impure virtual、non-virtual函数的接口继承和实现继承

    1.abstract class 拥有pure virtual函数的class是abstract class. 不能创建abstract class的实体. 2.pure virtual 函数 他们必 ...

随机推荐

  1. P4396 [AHOI2013]作业

    题目链接 luogu4396 思路 唯有水题暖人心 咕了4天,今天跟着std对拍才做出来不得不说题解真的水的一批 先离散化一下 第一问差分询问,权值树状数组套一套就好了 \(nlog_{n}\) 第二 ...

  2. How to create Excel file in C#

    http://csharp.net-informations.com/excel/csharp-create-excel.htm Before you create an Excel file in ...

  3. about MySQL Workbench的基本使用及运用操作

    http://blog.csdn.net/dongdong9223/article/details/48318877   <大神整理的更好!(评论里还有其他整理的) ↑ 使用MySQL Work ...

  4. 08_Flume_Selector实践

    实践一:replicating selector 1.目标场景 selector将event复制,分发给所有下游节点 2.Flume Agent配置 Agent配置 # Name the compon ...

  5. POJ 3624 Charm Bracelet(0-1背包模板)

    http://poj.org/problem?id=3624 题意:给出物品的重量和价值,在重量一定的情况下价值尽可能的大. 思路:经典0-1背包.直接套用模板. #include<iostre ...

  6. maven+nexus配置本地私有仓库

    以下是settting.xml的配置 <?xml version="1.0" encoding="UTF-8"?> <settings> ...

  7. codevs 1081 线段树练习 2 线段树

    题目描述 Description 给你N个数,有两种操作 1:给区间[a,b]的所有数都增加X 2:询问第i个数是什么? 输入描述 Input Description 第一行一个正整数n,接下来n行n ...

  8. windows 命令行中使用winrar

    加入环境变量即可 我的电脑右键属性->高级->环境变量->系统变量->编辑 变量名:path 变量值:C:/Program Files/WinRAR; --变量值为WinRAR ...

  9. 安装ceres-solver

    安装依赖: sudo apt-get install -y google-mock libboost-all-dev libeigen3-dev libgflags-dev libgoogle-glo ...

  10. Jmeter Connect to Cassandra

    https://github.com/Netflix/CassJMeter/wiki https://stackoverflow.com/questions/40974407/connecting-c ...