这个来源于需求,有的时候你只希望继承接口,有的时候你希望既继承接口又继承实现,并且还希望覆盖父类中已有的方法。这个标题就来源于这个需求。
在这里作者举了一个shape类的例子。这个shape类中有个纯虚函数,这使shape类成为一个抽象类,从而它不能拥有实例,而它的实现只能依靠它的子类来完成。例子中它的子类有两个一个是矩形一个是椭圆形。这两者都以public继承了shape类,很显然这必须要满足IS-A原则。
在shape类中有3个函数,它们是纯虚函数draw、普通虚函数error、普通非虚函数objectID。
纯虚函数的性质有二,1、它必须在子类中重新声明一下,2、通常来讲它在抽象类中没有实现。那么这两者结合在一块说明了什么呢?它说明这个函数接口存在的意义就是让你来继承的。
另外,纯虚函数通常是没有定义的,这说明什么呢?这说明在抽象类中纯虚函数可以有自己的实现,只不过一般人家不写,因为反正这是给别人去继承的。这一点很重要。
那么虚函数存在的意义是什么呢?它通常是有一份实现的,并且这份实现是默认的,还有它也是用来被继承的。因为凡是virtual的,都是一个virtual表,这个表里面都是指针,它们指向那些非virtual的函数。这就说明如果子类重写了该virtual函数,那么调用该子类的时候就使用这个重写后的实现。否则,就调用那个默认的实现。
那如果有的时候子类并未明确提出它想要使用这个默认的实现,同时它有没有自己去实现,这时候该咋办呢?现总结一下问题吧,问题是你现在肯定是要继承接口了,但是它那个默认的是实现你还不一定要。那就只能在父类中使用纯虚拟函数了,然后在纯虚拟函数中去掉用另外一个正常的成员函数,这个正常的成员函数是其默认实现。
但要记住本原则的目标是要实现接口和实现的分离,通俗来讲就是你要继承接口的时候你就只继承接口,你要使用默认的实现的时候就能使用默认的实现,你要是不想使用默认的实现你就自己写一个实现出来用。那么如何达到这个目的?其实很简单,具体做法就是让父类中的纯虚函数拥有自己的一份实现代码。因为纯虚函数肯定要被继承,但是它不强求你去掉用它的默认代码,这就说明当你在子类中写了一个函数声明但不给出实现的时候,它不会去自动调用纯虚函数的实现。而如果说你要使用纯虚函数的实现,那你可以使用类名进行限定,这样就能调用纯虚函数的实现代码了。那么这样的话,你只需要在子类的函数实现中通过类名指定父类中的纯虚函数的实现即可。
下面只剩下父类中的那个普通成员函数没有讨论到了,就是那个objectID。那么这个普通的成员函数存在的意义是什么呢?其实就是无论你子类怎么变,我这个行为就是不变的,你子类直接用就可以了,也就是说一般来讲它是不变的。
这里不得不再谈谈80-20法则。这个法则是什么意思呢?就是说程序执行时间的80%要花在只占工程总量20%的代码身上,而这个代码表示的是逻辑的实现算法的设计上面,而由语言机制带来的效率问题只占小部分,所以一般情况下,我们写程序不要舍本逐末,只见树木不见森林。
好了,现在总结一下作者的观点:
1、对接口继承和实现继承要区别对待,在public继承之下,父类接口总是要被子类继承的;
2、纯虚函数只是接口继承;
3、非纯虚函数既指定接口继承也要继承缺省实现;
4、非virtual函数应该原封不动地继承。
原则34:区分接口继承和实现继承
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- Android NDK开发之旅 目录 C++ 继承 面向对象程序设计中最重要的一个概念是继承。继承允许我们依据另一...