effective C++读书笔记六 —— 继承与面向对象设计

来源:互联网 发布:淘宝手提包批发 编辑:程序博客网 时间:2024/05/14 12:48

29 条款32:确定你的public继承塑模出is-a关系

       Public继承意味is-a。适用于base classes身上的每一件事情一定也要适用于derived classes身上。因为每一个derived class对象也都是一个base class对象。

30 条款33:避免遮掩继承而来的名称

       derived classes内的名称会遮掩base classes内的名字。为了让遮掩的名称再见天日,可使用using 声明式或转交函数。

       转交函数:在子类声明一个同名函数,并把子类private继承父类,子类中的同名函数调用父类对应的函数。

31 条款34:区分接口继承和实现继承

1)接口继承和实现继承不同,在public继承之下,derived classes总是继承base classes的实现继承。

2)声明一个pure virtual函数的目的是为了让derived classes只继承函数接口。

3impure virtual函数是具体接口继承及缺省实现继承

4non-virtual函数具体接口继承以及强制性实现继承。

32 条款35:考虑virtual函数以为的其他选择

1virtual函数的替代方案包括NVI手法及strategy设计模式的多种形式。NVI手法自身是一个特殊形式的Template method设计模式。NVI手法就是“令客户通过public non-virtual成员函数间接调用private virtual函数”。重新定义virtual函数表示某些事“如何”被完成,“调用virtual函数”表示它“何时”被完成。NVI手法允许derived classes重新定义virtual函数,从而赋予它们“如何实现机能的”控制能力,但base class保留诉说“函数何时被调用”的权利。

2)将virtual 函数替换为“函数指针成员变量”,这是strategy设计模式的一种分解表现形式。

3)以tr1::function成员变量替换virtual函数,因而允许使用任何可调用物搭配一个兼容于需求的签名式。这也是Strategy设计模式的某种形式。

4)将继承体系内的virtual函数替换为另一个继承体系内的virtual函数。这是strategy设计模式的传统实现手法。

33 条款36:绝不重新定义继承而来的non-virtual函数

1virtual函数和non-virtual函数区别:virtual函数是动态绑定的,而non-virtual函数是静态绑定的。

2)绝不重新定义继承而来的non-virtual函数。

34条款37:绝不重新定义继承而来的缺省参数值

(1)       virtual函数系统动态绑定,而虚函数的缺省参数值确实静态绑定的。原因:运

行期的效率决定的,如果是动态绑定,编译器就必须有某种办法在运行为virtual函数决定适当的缺省参数值。这比“在编译期决定”的机制更慢而且更复杂。

(2)       提供给basederived class的用户,会出现代码重复问题,并且带着相依性,

如果base class改变,所有“重复给定缺省参数值”的那些derived classes的也须改变,否则会导致“重复定义一个继承而来的缺省参数值”问题,应该采用替代方案NVI方式。令base class内的一个public non-virtual函数调用private virtual函数,后者可被derived classes重新定义。

35 条款38:通过复合塑模出has-a或“根据某物实现出”

       1)复合的意义跟public继承完全不同.。复合意味has-a(有一个,在应用领域)或is-implemented-in-terms-of(根据某物实现出,在实现域)。“Public继承”带有is-a(是一种)的意义。

2)记住标准库中的set可以由list实现,而不是继承而来。

36.条款39:明智而审慎地使用private继承

       1)如果class之间的继承关系是private。编译器不会自动将一个derived class对象转化为一个base class对象。由private base class继承而来的所有成员,在derived class中都会变成private属性,纵使它们在base class中原来是protectedpublic属性。

       2private继承意味is-implemented-in-terms-of根据某物实现出,尽可能使用复合,必要时才使用private继承。当protected成员和/virtual函数牵扯进来的时候,其实还有一种激进情况。那是当空间方面厉害关系足以踢翻private继承的支柱时。

       3private继承主要用于“当一个意欲成为derived class者想访问一个意欲为base class者或为了重新定义一个或多个virtual 函数”。有一种激进情况涉及空间优化,可能会促使你选择“private继承”而不是“继承加复合”。

       比如:

class Empty{};

clsss HoldsAnyInt{

private:

  int x;

  Empty e;

};//这个的大小为>sizeof(int),Empty空对象需要安插一个char到空对象,并且有齐位需求。

 

class HoldsAnyInt::private Empty{

private:

  int x;

}; //这个sizeof大小为sizeofint

4)一个混合public继承和复合的设计,往往能够替代private继承。

37 条款40:明智而审慎地使用多重继承

1)多重继承比单一继承更复杂,它可能导致新的歧义性,以及对virtual继承的需要。即使两个函数只有一个可用(一个为public,一个为private),这与C++解析重载函数调用的规则相符,C++确认这个函数对此调用之言的是最佳匹配,找出最佳匹配函数后才检验其可用性。

2)如果多种继承的两个base class都同时继承一个base class,会导致出现有两份相同的成员变量名,但是逻辑告诉我们不应该存在重复的成员变量。C++会采用虚拟继承父类,C++中包含的多种继承类有:basic_ios, basic_istream, basic_ostream, basic_iostream.

(3) virtual继承会增加大小、速度、初始化复杂度等成本。所以忠告:第一,非必要不使用virtual bases,平常请使用non-virtual继承。第二,如果你必须使用virtual base classes,尽可能避免在其中放置数据。

4)多重继承的确有正当用途,其中一个是涉及“public继承某个interface class”和“private继承某个协助实现的class”的两相结合。