`
xuela_net
  • 浏览: 494432 次
文章分类
社区版块
存档分类
最新评论

C++中的接口继承和实现继承

 
阅读更多

C++中的接口继承和实现继承


很多人认为,C++中是不存在接口继承的,只有Java、C#这类语言才提供了相应的语法支持。

但是,如同鲁迅说过的某句名言:世上本没有接口继承,用的人多了,才有了接口继承。C++中依然可以实现接口继承,只是形式上稍有不同罢了。

C++中的继承基于一个事实:父类定义的成员函数会一直被子类继承(包括被子类隐藏的部分)。

而父类中提供的函数可以有三种:1)普通成员函数 2)普通虚函数 3)纯虚函数。这三种函数类型代表了三种继承设计模式。

一个简单的实例代码如下:

01 classShape
02 {
03 public:
04 virtualvoidDraw() = 0;
05 virtualintGetError();
06 intGetId();
07 };
08
09 classRectangular :publicShape
10 {
11 //...
12 };
13
14 classCircle :publicShape
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 =newRectangular;
2 assert(p != NULL);
3
4 // invoke defaulat implementation of the pure-virtual function
5 p->Shape::Draw();
6
7 // doing something later
8 deletep;

那么这种让人觉得操蛋的trick有没有什么应用呢?

假设你有一个父类F,定义了一个普通虚函数,子类A,B都使用默认的虚函数实现。但是某天你需要增加一个新的子类C,但是这个子类不能使用默认的实现,必须重写。

不幸的是,你忘了重写这个函数,所以编译器为你调用了默认实现,于是意外的结果让你蛋碎了一地。

很明显,使用带有实现的纯虚函数就可以解决这个问题。纯虚函数会强制要求你重写虚函数,而你也可以在需要默认实现时通过显式调用完成相应工作。

不过需要这种trick的情况相当罕见,而且多半是设计出了问题或者完全可以人为避免。

分享到:
评论

相关推荐

    c++抽象类继承

    一个student类,lectureTeatre类,继承抽象module类,通过继承来实现接口

    面向接口的C++编程技术研究

    结合C++开发工程实践,分析了目前C++开发所面临的问题,包括C++缺少二进制级标准导致的可移植性问题,和C++头文件不能完全隐藏实现部分而导致的封装性问题。分析了目前C++开发的2种通知机制的问题,包括使用虚函数继承...

    关于C++中菱形继承和虚继承的问题总结

    在多重继承中建议使用“接口”,来避免多重继承中可能出现的各种问题。本文将给大家详细介绍关于C++菱形继承和虚继承的相关内容,分享出来供大家参考学习,话不多说了,来一起看看详细的介绍吧。 继承:  1. 单继承...

    C++编程思想--多重继承

    子对象重叠,虚基类,开销,向上映射,避免MI,修复接口

    C++类库接口说明文档

    .chm格式的C++常见API接口查询帮助文档 帮助了解各个常见接口的使用方法 继承图谱

    C++面向对象特性实现机制的初步分析

    类继承的内存结构,子类,父类之间的关系 接口继承和实现继承 继承带来的开销 <br/> 4多态 多态--就是指事物不同的方面 虚函数 纯虚函数,虚拟继承 虚函数与函数重载的区别...

    c++多重继承

    类的多重继承演示"<<endl; CDateTimeType dt 1 1 2008 11 12 12 ; 直接使用DateTimeType构造函数设置日期时间 cout<<"调用CDateTimeType类构造函数设定的初始日期 时间为:"<<...

    课程设计大作业C++基于Qt实现系统中设备管理功能(热插拔监测)源码.zip

    课程设计大作业C++基于Qt实现系统中设备管理功能(热插拔监测)源码。 主要功能 通过继承QAbstractNativeEventFilter接口实现串口热插拔监测功能; 通过在QWidget中重写nativeEvent实现串口热插拔监测功能; 通过一...

    C++ 中私有继承的作用

    C++ 中私有继承的作用 私有继承的 第一个规则:和公有继承相反,如果两个类之间的继承关系为私有,编译器一般不会将派生类对象转换成基类对象。 第二个规则: 从私有基类继承而来的成员都成为了派生类的私有成员,...

    C++编程思想习题

    14.4C++如何实现晚捆绑 14.4.1存放类型信息 14.4.2对虚函数作图 14.4.3撩开面纱 14.4.4安装vpointer 14.4.5对象是不同的 14.5为什么需要虚函数 14.6抽象基类和纯虚函数 14.7继承和VTABLE 14.8虚函数和构造函数 ...

    C++继承多接口,调用虚函数跳转到错误接口的虚函数的奇怪问题demo

    C++继承多接口,调用虚函数跳转到错误接口的虚函数的奇怪问题,一个示例的dmeo

    C++:通过私有(private)继承复用类实现工厂函数详解

    C++:通过私有(private)继承复用类实现工厂函数详解。

    C++ 多态和虚函数 高清PDF

    多态性(在C + +中用虚函数实现)是面向对象程序设计语言继数据抽象和继承之后的第三个基本特征。 它提供了与具体实现相隔离的另一类接口,即把“ w h a t”从“h o w”分离开来。多态性提高了代码的组织性和可读性...

    工厂模式与面向接口配合实现深度解耦

    在Java和C#的编程世界里,并没有出现像C++那样的多脉继承,它们只支持单一的继承,或者多级继承,这一变化最大的影响,我觉得是大大的降低了编程的难度,因为没有了C++的多级多脉继承,所以接口出现了,它支持多重...

    C++中抽象类和接口的区别介绍

    如果一个类B在语法上实现了(implement)接口I, 那么类B遵从接口I制定的协议. 使用abstract class的根本原因在于, 人们希望通过这样的方式, 表现不同层次的抽象. 而interface的本质是一套协议. 在程序设计的发展中, ...

    C++讲义及习题指导

    (7)C++语言支持动态联编 多态性是指在基类中定义的属性和服务被子类继承后,可以具有不同的数据类型和表现出不同的行为。当一个对象接收到一个请求进行某项服务的消息时,将根据对象所属的类,动态地选用该类中定义...

    C++中的封装、继承、多态理解

    封装的目的是增强安全性和简化编程,使用者不必了解具体的实现细节,而只是要通过外部接口,特定的访问权限来使用类的成员。封装可以隐藏实现细节,使得代码模块化。 继承(inheritance):C++通过类派生机制来支持...

    Effective C++

    条款36:区分接口继承与实现继承 条款37:绝不要重新定义继承而来的非虚函数 条款38:绝不要重新定义继承而来的缺省参数值 条款39:避免向下转换继承层次 条款40:通过分层来体现有一个和用...来实现 条款41:区分继承和...

    c/c++中如何实现动态库动态加载的完整工程示例代码

    c/c++中如何实现动态库动态加载的完整工程示例代码: 本代码将将win、linux加载、卸载动态库,并从动态库链接模块中获取类实例或函数地址等封装成统一的API接口,并集成在dllLoad.h/dllLoad.cpp中实现。构建一个注册...

    Effective C++ 中文版

    条款34:区分接口继承和实现继承 条款35:考虚virtual函数以外的其他选择 条款36:绝不重新定义继承而来的non-virtual函数 条款37:绝不重新定义继承而来的缺省参数值 条款38:通过复合塑模出has-a或“根据某物...

Global site tag (gtag.js) - Google Analytics