设为首页 加入收藏

TOP

5.5 C++的划分:私有、保护和公有继承
2013-10-07 14:33:06 来源: 作者: 【 】 浏览:60
Tags:5.5 划分 私有 保护 公有 继承

5.5  C++(www.cppentry.com)的划分:私有、保护和公有继承

如果你是一个C++(www.cppentry.com)程序员,或者你将成为一个C++(www.cppentry.com)程序员,那么关于继承关系还有一个值得注意的地方。C++(www.cppentry.com)语言实现了私有继承、保护继承和公有继承这3种关系。公有继承关系和面向对象范型中对继承的定义是等价的。私有和保护继承则用来表示"为了实现而继承"。这两种关系的语义是,派生类获得基类的数据的一份拷贝(访问权限与公有继承是一样的),派生类的实现者可以访问基类的公有区域,但是派生类的使用者无法访问基类的公有区域。简而言之,私有继承和保护继承就是包含关系。它们既没有表示特化也没有表示分类。私有和保护继承的不同在于,保护继承允许派生类的派生类的实现者使用基类的公有区域,但是私有继承不允许。

因为在C++(www.cppentry.com)中类只能被继承一次,所以这两种关系实际上是包含关系的一种变型,特殊之处在于包含类只能包含指定类型的一个对象。关于C++(www.cppentry.com)的一条好的经验原则是避免使用私有继承和保护继承,而代之以通过数据成员的包含。我可以找出很多C++(www.cppentry.com)程序员,他们声称他们知道自己在做什么,并且希望用C++(www.cppentry.com)的继承关系来实现包含。但是他们给负责维护他们的程序的人带来了很大的麻烦(而且这些维护工作有可能会是在3个月之后由他们自己来做,但那时他们已经不记得自己实现了什么了)。在面向对象范型中一个严重的陷阱是混淆了包含关系和继承关系的用法。使用继承语法来实现包含关系把水搅得更混了。为了可读性,在C++(www.cppentry.com)语言中应该只使用公有继承。

在5.8所示的例子中,下列的事实均成立,不管所使用的继承的形式是什么(私有、保护或者公有继承)。

1.类的私有区域中的任何东西都只能被类的实现者访问。也就是说,水果类的实现者可以访问水果类的私有区域中的weight和color,而只有苹果类的实现者可以访问苹果类的私有区域中的taste和seednum,只有Macintosh苹果类的实现者可以访问Macintosh苹果类的私有区域中的OrchardLocation。

2.类的保护区域中的任何东西都只能由该类或者派生类的实现者访问。也就是说,水果类的get_weight方法可以被水果、苹果和Macintosh苹果的实现者访问,苹果的get_seednum方法可以被苹果和Macintosh苹果的实现者访问。

 
图5.8  公有、保护和私有继承的不同

3.类的公有区域中的任何东西都可以被类的实现者或者类的直接使用者访问。也就是说,水果类的print、cost和eat方法对水果的实现者和使用者都是可见的,苹果的core和bake方法对苹果的实现者和使用者都是可以见的,Macintosh苹果的pick_your_own方法对于Macintosh苹果的实现者和使用者都是可见的。

4.类的公有接口中的任何东西都可以被直接派生类的实现者访问。也就是说,水果类的print、cost和eat方法对于苹果的实现者都是可见的;苹果的bake和core方法对Macintosh苹果的实现者是可见的。

还剩下的问题是:

苹果的使用者可以访问水果的公有接口吗?

Macintosh苹果的使用者可以访问苹果的公有接口吗?

Macintosh苹果的实现者可以访问水果的公有接口吗?

如果我们使用公有继承,那么对上面3个问题的答案都是"是",因为公有继承的语义就如同把基类的公有接口复制到派生类的公有接口中去。如果我们使用保护继承,那么苹果和Macintosh苹果的使用者就无法访问eat、cost和print操作,这是因为保护继承的语义就如同把基类的公有接口复制到派生类的保护接口中去,而类的使用者不能访问类的保护区域中的内容。但是,Macintosh苹果的实现者可以访问苹果的保护区域,所以她们可以使用水果的公有方法。因此,对这3个关键问题的答案依次是:否、否、是。最后,如果我们使用私有继承,那么所有3个问题的答案均是"否",因为私有继承的语义就如同把基类的公有接口复制到派生类的私有接口中去,而只有类的实现者才能看到这个类的私有成员。

如果你觉得上面这些令人迷惑,那么你并不孤独。很多人都觉得这令人迷惑。私有继承和保护继承只是变型的包含关系,应当避免。不过既然C++(www.cppentry.com)实现了这些概念,那么就值得在本书中提到它们。本书后面部分说到的继承都等同于C++(www.cppentry.com)中的公有继承。我并没有给出一条经验原则,让设计者避免使用私有和保护继承,这是因为我希望经验原则是独立于语言的。而且,这两种构造都有扎实的理论依据(为了实现的继承)。采用它们的真正问题在于,阅读使用了这些构造的代码的系统构架师很难理解这些用法。他在看见私有继承的时候很可能会以为是特化语义,但是实际上这是包含关系。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇C++ 98中的新语言特性 下一篇解析Java语言11个主要特性

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: