谨慎使用私有继承(2)
2008-02-23 05:28:49来源:互联网 阅读 ()
这是个很好的设计,但值得注意的是,private inheritance(私有继承)并不是绝对必要的。假如我们决定用 composition(复合)来代替,也是能够的。我们仅需要在我们从 Timer 公有继承来的 Widget 内声明一个 private nested class(私有嵌套类),在那里重定义 onTick,并在 Widget 中放置一个那个类型的 object(对象)。以下就是这个方法的概要:
class Widget {
private:
class WidgetTimer: public Timer {
public:
virtual void onTick() const;
...
};
WidgetTimer timer;
...
};
这个设计比只用了 private inheritance(私有继承)的那一个更复杂,因为他包括 (public) inheritance((公有)继承)和 composition(复合)两者,连同一个新 class (WidgetTimer) 的引入。老实说,我出示他主要是为了提醒您有多于一条的道路通向一个设计问题,而且他也能够锻炼您自己您自己考虑多种方法(参见《C 箴言:最小化文档之间的编译依赖》)。然而,我能够想到为什么您可能更愿意用 public inheritance(公有继承)加 composition(复合)而不用 private inheritance(私有继承)的两个原因。
首先,您可能要做出允许 Widget 有 derived classes(派生类)的设计,但是您还可能要禁止 derived classes(派生类)重定义 onTick。假如 Widget 从 Timer 继承,那是不可能的,即使 inheritance(继承)是 private(私有)的也不行。(回忆《C 箴言:考虑可选的虚拟函数的替代方法》derived classes(派生类)能够重定义 virtual functions(虚拟函数),即使调用他们是不被允许的。)但是假如 WidgetTimer 在 Widget 中是 private(私有)的而且是从 Timer 继承的,Widget 的 derived classes(派生类)就不能访问 WidgetTimer,因此就不能从他继承或重定义他的 virtual functions(虚拟函数)。假如您曾在 Java 或 C# 中编程并且错过了禁止 derived classes(派生类)重定义 virtual functions(虚拟函数)的能力(也就是,Java 的 final methods(方法)和 C# 的 sealed),现在您有了一个在 C 中的到类似行为的想法。
第二,您可能需要最小化 Widget 的 compilation dependencies(编译依赖)。假如 Widget 从 Timer 继承,在 Widget 被编译的时候 Timer 的 definition(定义)必须是可用的,所以定义 Widget 的文档可能不得不 #include Timer.h。另一方面,假如 WidgetTimer 移出 Widget 而 Widget 只包含一个指向一个 WidgetTimer 的 pointer(指针),Widget 就能够只需要 WidgetTimer class(类)的一个简单的 declaration(声明);为了使用 Timer 他无需 #include 任何东西。对于大型系统,这样的隔离可能很重要(关于 minimizing compilation dependencies(最小化编译依赖)的细节,参见《C 箴言:最小化文档之间的编译依赖》)。
我早些时候谈及 private inheritance(私有继承)主要用武之地是当一个将要成为 derived class(派生类)的类需要访问将要成为 base class(基类)的类的 protected parts(保护构件),或希望重定义一个或多个他的 virtual functions(虚拟函数),但是 classes(类)之间的概念上的关系却是 is-implemented-in-terms-of,而不是 is-a。然而,我也说过有一种涉及 space optimization(空间最优化)的极端情况可能会使您倾向于 private inheritance(私有继承),而不是 composition(复合)。
这个极端情况确实很尖锐:他仅仅适用于您处理一个其中没有数据的 class(类)的时候。这样的 classes(类)没有 non-static data members(非静态数据成员);没有 virtual functions(虚函数)(因为存在这样的函数会在每一个 object(对象)中增加一个 vptr ——参见《C 箴言:多态基类中将析构函数声明为虚拟》);也没有 virtual base classes(虚拟基类)(因为这样的 base classes(基类)也会引起 size overhead(大小成本))。在理论上,这样的 empty classes(空类)的 objects(对象)应该不占用空间,因为没有 per-object(逐对象)的数据需要存储。然而,由于 C 天生的技术上的原因,freestanding objects(单独对象)必须有 non-zero size(非零大小),所以假如您这样做,
class Empty {}; // has no data, so objects should
// use no memory
class HoldsAnInt { // should need only space for an int
private:
int x;
Empty e; // should require no memory
};
您将发现 sizeof(HoldsAnInt) > sizeof(int);一个 Empty data member(空数据成员)需要存储。对以大多数编译器,sizeof(Empty) 是 1,这是因为 C 法则反对 zero-size 的 freestanding objects(单独对象)一般是通过在 "empty" objects(“空”对象)中插入一个 char 完成的。然而,alignment requirements(对齐需求)可能促使编译器向类似 HoldsAnInt 的 classes(类)中增加填充物,所以,很可能 HoldsAnInt objects 得到的不但仅是个 char 的大小,实际上他们可能会扩张到足以占据第二个 int 的位置。(在我测试过的任何编译器上,这毫无例外地发生了。)
但是也许您已注意到我小心翼翼地说 "freestanding" objects(“单独”对象)必然不会有 zero size。这个约束不适用于 base class parts of derived class objects(派生类对象的基类构件),因为他们不是单独的。假如您用从 Empty 继承代替包含一个此类型的 object(对象),
class HoldsAnInt: private Empty {
private:
int x;
};
您几乎总是会发现 sizeof(HoldsAnInt) == sizeof(int)。这个东西以 empty base optimization (EBO)(空基优化)闻名,而且他已被我测试过的任何编译器实现。假如您是个空间敏感的客户的库研发者,EBO 就值得了解。同样值得了解的是 EBO 通常只在 single inheritance(单继承)下才可行。支配 C object layout(C 对象布局)的规则通常意味着 EBO 不适用于拥有多于一个 base(基)的 derived classes(派生类)。
在实践中,"empty" classes(“空”类)并不真的为空。虽然他们绝对不会有 non-static data members(非静态数据成员),但他们经常会包含 typedefs,enums(枚举),static data members(静态数据成员),或 non-virtual functions(非虚拟函数)。STL 有很多包含有用的 members(成员)(通常是 typedefs)的专门的 empty classes(空类),包括 base classes(基类)unary_function 和 binary_function,user-defined function objects(用户定义函数对象)通常从这些 classes(类)继承而来。感谢 EBO 的普遍实现,这样的继承很少增加 inheriting classes(继承来的类)的大小。
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇: 创建和使用库:静态、共享和动态
下一篇: C 中extern
- C 箴言:谨慎使用私有继承(1) 2008-02-23
- C 箴言:谨慎使用私有继承 2008-02-23
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash
