原则39:明知而审慎地使用PRIVATE继承

Private继承和public继承是软件生产中两个不同层面上的东西。Public侧重的是业务逻辑,它是从用户角度来想问题的。而private则纯粹是从实现角度来讲的,它意味着is-implemented-in-terms-of,即根据某物实现出什么的意思。
首先看一个例子:




可以看出通过子类对象无法调用父类的公有接口,而child和base是通过private方式继承的。这说明通过private方式继承的子类对象并不是一个父类对象,即不是IS-A的关系。
在面向对象程序设计的过程通常是模块化编程,每个模块是按照功能进行划分的,模块之外的通常都是用户,用户可调用的就是这个模块提供的接口,它们通常是public成员函数。而private继承体现了模块内部纯粹的实现细节和代码重用,因此private继承主要用在应用已经存在的具体实现实现出新的实现。
那这里private和复合都是is-implemented-in-terms-of关系,用哪个好呢?在这里作者极力推荐使用复合,不到万不得已不使用private继承,这倒不是说private继承不好,只是想表达private继承没啥必要,但是为啥没必要作者并未提及,作者只是说实现途径不只有private而已,这不禁让我感觉作者是在炫技或者纯粹是别出心裁思维的一种表述。
那么这个万不得已的时候是什么时候?作者说当涉及到protected成员、virtual成员函数、空间被限制得特别小特别严格的时候。
作者举了一个例子用来说明一种方案来代替private继承,我在这里就不再赘述这个例子是啥了,我只说说原理就OK了。因为当父类中含有virtual函数的时候,由于virtual函数的特性使之可在子类中被重新定义,因此不适宜使用public继承,不使用public继承,那自然就不满足IS-A的关系啦。
在这里使用private继承是一种好的选择,因为它有效地隐藏实现的细节,并且提供一个不具二义性的接口给用户。
它的一个替代实现方案是最靠近的是一个功能类A,它需要用到类B的实现,而这个类B又具备类C的所有特性。那现在的设计就是类A中包含了private的类B,并且类B以public方式继承了类C。然后在类A中以private方式声明一个类B的对象。这样所有涉及到virtual函数的重定义方面的事情都集中到B中进行处理和A一点关系都没有。这也是实现数据封装的一种方式,以后即便类A拥有自己的子类D,D也不会涉及到处理virtual函数的事。这样做也可以降低编译相依性,因为如果A直接继承C势必会导致加载C所在头文件,而如果按照上述方案A只需要B的一个声明。作者提到的这个方案还是个重要的解耦方案呢。
为什么说private继承适用于那些父类中有protected和virtual函数的场合呢?那是因为在private继承下继承的protected成员到子类中就是子类的private成员,父类的private成员还是父类的private成员跟子类一点关系都没有,而父类的public成员是面向用户的,它不需要子类去继承。所以你可以看出但凡是需要private继承的父类中最多只含有protected和private成员。而父类中如果含有virtual函数,那么它存在的目的就是要你去重定义,或者使用默认的实现,它不是public接口,还是实现的层面,而子类实现出来的东西就不是父类中的原版了,也就是说这不是IS-A的关系了,自然就不是public继承。那就只可能是private和protected继承了。而在这里我大胆地猜想protected继承应该是适用于那些连续继承实现的场合吧。因为如果是private继承,父类中的非private成员都会变成子类的private继承,而子类的private成员无论通过什么继承方式都无法再被其他类继承了。所以我觉得private继承是protected继承的终结。
那么对空间限制非常严格非常小的场合又是什么呢?这涉及到空类的继承与复合的区别。现在假设类A是空类,里面啥都没有,类B是正常类,那么有B复合A所占用的空间比B继承A所占用的空间大。具体来讲B中的各成员的存储的时候要求对齐存储,这一点我在《C与指针》有关结构体各成员在内存中的存储情况有过记录,类中各成员的存储情况也是类似的。而且一般来讲一个空类的对象所占的空间也不是0,一般情况下是1byte,因为C++规定一个独立的对象所占用的空间必须非0。这就决定你在采用复合时那个复合类对象所占用的空间中空类成员占用不只1byte。而你如果继承空类,那么子类对象中空类成分占用0byte。这种技巧被称为EBO(empty base optimization,空白基类最优化),不过它一般用于单继承。
它的作用在一般情况下是体现不出来的,因为一般的存储空间已经足够大了。它的实用性真正体现在像什么嵌入式这种空间非常小的场合。还有这个EBO技术所说的空类,其实也并不是啥都没有,typedef、enum、static、非virtual函数还是可能有的。请看下图:





其实,只要类中不含有非static成员变量,它就被认为是空的,比如说我再往上述例子中添加一个非static成员变量再看。



最后作者总结道:
1、private继承强调的是实现,它比复合低。当子类需要访问父类中的protected成员或者父类中还有virtual函数时,你需要private继承。
2、private是和空间最优化设计。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,383评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,522评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,852评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,621评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,741评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,929评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,076评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,803评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,265评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,582评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,716评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,395评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,039评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,027评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,488评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,612评论 2 350

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,637评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,599评论 18 399
  • 一:java概述:1,JDK:Java Development Kit,java的开发和运行环境,java的开发工...
    ZaneInTheSun阅读 2,635评论 0 11
  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,087评论 0 62
  • “妈妈,我也想去!”这句话已经唠叨了2天了。 女儿学校组织“奔跑吧少年”少儿活动,限15人。班主任在群里发布消息,...
    彭晓芬阅读 177评论 0 0