1.接口继承与实现继承的区别

《Effective C++》条款三十四:区分接口继承和实现继承中介绍的比较啰嗦,概括地说需要理解三点:

(1)纯虚函数只提供接口继承,但可以被实现;

(2)虚函数既提供接口继承,也提供了一份默认实现,即也提供实现继承;

(3)普通函数既提供接口继承,也提供实现继承。

这里假定讨论的成员函数都是public的。

这里回顾一下这三类函数,如下:

class BaseClass
{
public:
     void virtual PureVirtualFunction() = 0; // 纯虚函数
     void virtual ImpureVirtualFunction(); // 虚函数
     void CommonFunciton(); // 普通函数
 }; 

纯虚函数有一个“等于0”的声明,具体实现一般放在派生中(但基类也可以有具体实现),所在的类(称之为虚基类)是不能定义对象的,派生类中仍然也可以不实现这个纯虚函数,交由派生类的派生类实现,总之直到有一个派生类将之实现,才可以由这个派生类定义出它的对象。

虚函数必须有实现,否则会报链接错误。虚函数可以在基类和多个派生类中提供不同的版本,利用多态性质,在程序运行时动态决定执行哪一个版本的虚函数(机制是编译器生成的虚表)。virtual关键字在基类中必须显式指明,在派生类中不必指明,即使不写,也会被编译器认可为virtual函数,virtual函数存在的类可以定义实例对象。

普通函数则是将接口与实现都继承下来了,如果在派生类中重定义普通函数,将同名函数隐藏。事实上,也是极不推荐在派生类中隐藏基类的普通函数,如果真的要这样做,请一定要考虑是否该把基类的这个函数声明为虚函数或者纯虚函数。

下面看一个示例程序。

CShape是一个几何图形的基类,对于任何一个几何图形来说,绘制和设置颜色都是合理的操作,因此可以按照如下方式设计类:

class CShape{
public:
    virtual void draw()=0;
    virtual void setColor(const Color& color);
private:
    Color m_color;
};

class CCircle:public CShape{};
class CEllipse:public CShape{};

上面几个类的申明就可以很好的展示继承的两个相互独立的部分:函数接口继承(inheritance of function interfaces)和函数实现继承(inheritance of function implementations)。

在基类CShape中,不能够为每一种不同的图形提供一个默认的draw实现,所以设置为纯虚函数,留给派生类来实现,也就说派生类只是继承了一个借口而已。圆和椭圆有着自己的绘制方式,所以各自有独自的绘制实现。

对于CShape::setColor,将其设置为普通的虚函数,提供一个默认的实现,这样圆和椭圆既可以重新定义,也可以使用基类的默认实现。使用普通的虚函数,派生类既使用了接口继承,也使用了实现继承。

2.接口继承与实现继承的选择

类设计时,接口继承与实现继承相互独立,代表着一定的设计意义,在二者之间进行选择时,我们需要考虑一个因素:对于无法提供默认版本的函数接口选择函数接口继承,对于能够提供默认版本的函数接口,选择函数实现继承。


参考文献

[1]读书笔记Effective_C++条款三十四:区分接口继承和实现继承

[2]李健.编写高质量代码:改善C++程序的150个建议[M].第一版.北京:机械工业出版社,2012.1:314-315

C++接口继承与实现继承的区别和选择的更多相关文章

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

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

  2. Effective C++:规定34:区分接口继承和实现继承

    (一个) class Shape { public: virtual void draw() const = 0; virtual void error(const string& msg); ...

  3. 7 -- Spring的基本用法 -- 8... 抽象Bean与子Bean;Bean继承与Java继承的区别;容器中的工厂Bean;获得Bean本身的id;强制初始化Bean

    7.8 深入理解容器中的Bean 7.8.1 抽象Bean与子Bean 把多个<bean.../>配置中相同的信息提取出来,集中成配置模版------这个配置模版并不是真正的Bean,因此 ...

  4. java一个类 继承HttpServlet 和实现Servlet区别

    java一个类 继承HttpServlet 和实现Servlet区别 servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法 而HttpServlet实现了servlet接 ...

  5. Effective C++ -----条款34:区分接口继承和实现继承

    接口继承和实现继承不同.在public继承之下,derived classes总是继承base class的接口. pure virtual函数只具体指定接口继承. 简朴的(非纯)impure vir ...

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

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

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

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

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

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

  9. [Java] 类和接口的初始化步骤 - 继承方面

    类和接口在初始化化时,处理继承层级的方法不一样. 类继承的初始化:通过引用 static 字段,触发某个类的初始化,则声明该字段的类,以及该类的父类被初始化. 接口继承的初始化:通过引用 static ...

随机推荐

  1. HTML基础范例

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. python-GUI之tkinter的学习

    最近看了哔哩哔哩的python的学习,直接看代码吧,以后会更新 先来个基础的 import tkinter as tk #导入包 app = tk.Tk() #抽象出一个GUI app.title(& ...

  3. Netty源码分析第5章(ByteBuf)---->第5节: directArena分配缓冲区概述

    Netty源码分析第五章: ByteBuf 第五节: directArena分配缓冲区概述 上一小节简单分析了PooledByteBufAllocator中, 线程局部缓存和arean的相关逻辑, 这 ...

  4. spring-framework-reference(5.1.1.RELEASE)中文版——Core部分

    前言 最近在学习Spring框架,在学习的同时,借助有道翻译,整理翻译了部分文档,由于尚在学习当中,所以该篇文章将会定时更新,目标在一个月左右时间翻译完全部版本. 虽然大部分内容为翻译,但是其中可能会 ...

  5. PHP 包含文件

    1.require test123.php <?php $a=1; 运行文件: <?php require('test123.php'); echo 'Hello!'; echo '< ...

  6. Redis Jedis简介

    Redis是一种基于内存类型的数据存储工具 Jedis是一个用java写的Redis数据库操作的客户端,通过Jedis,可以很方便的对redis数据库进行操作.Jedis通过Jedis Pool进行R ...

  7. head和tail命令详解

    基础命令学习目录首页 原文链接:https://www.cnblogs.com/amosli/p/3496027.html 当要查看上千行的大文件时,我们可不会用cat命令把整个文件内容给打印出来,相 ...

  8. 【quickhybrid】组件(自定义)API的实现

    前言 前文在API规划时就已经有提到过组件API这个概念,本文将会介绍它的原理以及实现 理解组件API这个概念 quick.ui.xxx quick.page.xxx 在quick hybrid中,A ...

  9. Notes of Daily Scrum Meeting(11.19)

    Notes of Daily Scrum Meeting(11.19) 现在工程项目进入尾声了,我们的项目中还有一些问题需要解决,调试修改起来进度比较慢,所以昨天就没有贴出项目 进度,今天的团队工作总 ...

  10. C++编译与链接(0)-.h与.cpp中的定义与声明

    C++中有的东西需要放在可以在.h文件中定义,有的东西则必须放在.cpp文件中定义,有的东西在不同的cpp文件中的名字可以一样,而有的则不能一样 那么究竟哪些东西可在头文件中定义,声明,哪些东西又必须 ...