C++接口继承与实现继承的区别和选择
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++接口继承与实现继承的区别和选择的更多相关文章
- Effective C++ 34 区分接口继承和实现继承
public继承从根本上讲,有两部分:接口继承和实现继承.两者之前的区别很像函数声明与函数定义. 具体设计中,会呈现三种形式:derived class只继承成员函数的接口(纯虚函数):derived ...
- Effective C++:规定34:区分接口继承和实现继承
(一个) class Shape { public: virtual void draw() const = 0; virtual void error(const string& msg); ...
- 7 -- Spring的基本用法 -- 8... 抽象Bean与子Bean;Bean继承与Java继承的区别;容器中的工厂Bean;获得Bean本身的id;强制初始化Bean
7.8 深入理解容器中的Bean 7.8.1 抽象Bean与子Bean 把多个<bean.../>配置中相同的信息提取出来,集中成配置模版------这个配置模版并不是真正的Bean,因此 ...
- java一个类 继承HttpServlet 和实现Servlet区别
java一个类 继承HttpServlet 和实现Servlet区别 servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法 而HttpServlet实现了servlet接 ...
- Effective C++ -----条款34:区分接口继承和实现继承
接口继承和实现继承不同.在public继承之下,derived classes总是继承base class的接口. pure virtual函数只具体指定接口继承. 简朴的(非纯)impure vir ...
- 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 函数 他们必 ...
- [Java] 类和接口的初始化步骤 - 继承方面
类和接口在初始化化时,处理继承层级的方法不一样. 类继承的初始化:通过引用 static 字段,触发某个类的初始化,则声明该字段的类,以及该类的父类被初始化. 接口继承的初始化:通过引用 static ...
随机推荐
- Hyperledger Fabric 账本结构解析
前言 现在很多人都在从事区块链方面的研究,作者也一直在基于Hyperledger Fabric做一些开发工作.为了方便后来人更快的入门,本着“开源”的精神,在本文中向大家讲解一下Hyperledger ...
- pssh命令详解
基础命令学习目录首页 原文链接:https://www.cnblogs.com/kevingrace/p/6378719.html pssh提供OpenSSH和相关工具的并行版本.包括pssh,psc ...
- RHEL6.4 xclock安装小记
http://blog.sina.com.cn/s/blog_623630d50101tc67.html
- Scurm Meeting 11.2
成员 今日任务 明日计划 用时 徐越 写功能规格说明书,代码移植 创建数据库,代码移植 3h 赵庶宏 编写功能规格说明书,学习访问数据库代码,代码迁移 代码迁移 5h 武鑫 设计界面:独立完成一些简单 ...
- c++第七次作业____最后的总结
先言: 在这过程中学到: 第二次作业Github的使用 第四次作业计算器的计算 ps:表达式处理以及计算 第五次作业文件的处理问题 第六次作业界面的设计 总结: 1.这学期的计算器,做的有点匆忙,偶尔 ...
- fcn模型训练及测试
1.模型下载 1)下载新版caffe: https://github.com/BVLC/caffe 2)下载fcn代码: https://github.com/shelhamer/fcn.berkel ...
- NABCD(网上投票系统)
网上投票系统 N(need) 投票这件事情,在所有事情上都可能用得到,在互联网的影响下,投票的范围变得越来越广,比如在商业的里,往往要做市场分析,那么在互联网这个大的前提下,用网上投票系统来获取用户的 ...
- RabbitMQ使用笔记
一.安装 1.下载所需安装包 下载服务端(原因在于RabbitMQ服务端代码是使用并发式语言erlang编写的):http://www.rabbitmq.com/install-windows.htm ...
- tomcat介绍
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由java语言编写,需要运行在jvm虚拟机中.之所以Java的应用 ...
- Hibernate(十)
1.批处理 //批处理 :批量处理 //批量插入数据 @Test public void addData(){ Random random=new Random(); for(int i=1;i< ...