《Effective C++》第六章:继承与面向对象设计
2017-06-27 17:56
330 查看
条款32:确定你的public继承塑模出is-a关系
is-a的关系就是说派生类一定是一个基类,额,通俗一点说就是派生类可以当做基类一样来使用。即本章阐述的观点就是,public继承就意味着is-a。适用于base classes身上的每一件事一定也适用于derived classes身上,确保base能做的事,derived也一定可以做
条款33:避免遮掩继承而来的名称
考虑下面这个例子:
条款34:区分接口继承和实现继承
身为class设计者,有时候你会希望只继承成员函数的接口(纯虚函数);有时候你又会希望derived class同时继承函数的接口和实现,但又希望能够覆写实现(虚函数);又有时候你希望derived class同时继承函数的接口和实现,但不允许覆写任何东西(普通函数)。
条款35:考虑virtual函数以外的其他选择
1、借由Non-Virtual Interface手法实现Template Mehod模式
即将virtual函数声明为private,由public非虚函数调用这个虚函数..就是在virtual实现了一层封装,可以在虚函数调用前后做一些操作
2、由函数指针实现回调
3、所谓的Strategy模式,个人理解为复合,将基类A当做一个类B的成员变量,这样的话,每个A的派生类都适用于B(而且A的派生类可能重写A中的虚函数),比如下面例子:
条款36:绝不重新定义继承而来的non-virtual函数
假设我们定义以下关系:
条款37:绝不重新定义继承而来的缺省参数值
由于上一条款绝不重新定义继承而来的non-virtual函数,所以本章讨论将局限于继承一个带有缺省参数值的virtual函数。那么本条款成立的理由十分明确:virtual是动态绑定,而缺省参数却是静态绑定。所以即使派生类重新定义了缺省参数值,参数值也不会表现为多态。解决方法是条款35提出的NVI(non-virtual-interface)手法,将缺省参数放在public非虚函数上,而将虚函数声明为private。
条款38:通过复合塑模出has-a或根据某物实现出
当复合发生于应用域的对象之间,表现出has-a的关系;当它发生于实现域内则是表现出根据某物实现出的关系。......抽象
条款39:明智而审慎的使用private继承
探讨的是private继承,public继承是is-a关系,而private继承纯粹是一种实现技术,意味着只有实现被继承,而接口被略去,即上一条款所说的根据某物实现出的概念。那么什么时候用复合,什么时候用private继承呢?首先我们从类的大小来分析。一个空类或者不含数据成员的类大小通常为1个字节,当使用复合的时候,这个类成员会占用4个字节,因为边界对齐。如果使用private继承,这个类是不占用空间的。另外如果想使用一个类的protected成员,那么必须是private继承了。
over...这一章节算是更完了
is-a的关系就是说派生类一定是一个基类,额,通俗一点说就是派生类可以当做基类一样来使用。即本章阐述的观点就是,public继承就意味着is-a。适用于base classes身上的每一件事一定也适用于derived classes身上,确保base能做的事,derived也一定可以做
条款33:避免遮掩继承而来的名称
考虑下面这个例子:
class Base { private: int x; public: virtual void mf1() = 0; virtual void mf1(int); virtual void mf2(); void mf3(); void mf3(double); }; class Derived:public Base { public: virtual void mf1(); void mf3(); void mf4() }; Derived d; int x; d.mf1(); d.mf1(x); //报错 d.mf2(); d.mf3(); d.mf3(x); //报错由此可见,派生类会遮掩基类的名称,无论重载。我们可以使用using来使得名字可见。
条款34:区分接口继承和实现继承
身为class设计者,有时候你会希望只继承成员函数的接口(纯虚函数);有时候你又会希望derived class同时继承函数的接口和实现,但又希望能够覆写实现(虚函数);又有时候你希望derived class同时继承函数的接口和实现,但不允许覆写任何东西(普通函数)。
条款35:考虑virtual函数以外的其他选择
1、借由Non-Virtual Interface手法实现Template Mehod模式
即将virtual函数声明为private,由public非虚函数调用这个虚函数..就是在virtual实现了一层封装,可以在虚函数调用前后做一些操作
2、由函数指针实现回调
3、所谓的Strategy模式,个人理解为复合,将基类A当做一个类B的成员变量,这样的话,每个A的派生类都适用于B(而且A的派生类可能重写A中的虚函数),比如下面例子:
class GameCharacter; class HealthCalcFucn { public: virtual int calc(const GameCharacter& gc) const; }; class GameCharacter { public: explicit GameCharacter(HealthCalcFucn *phcf); int healthValue() { pHealthCalc(*this); } private: HealthCalcFucn *pHealthCalc; }这样每个HealthCalcFunc的派生类都适用于GameCharacter这个类。
条款36:绝不重新定义继承而来的non-virtual函数
假设我们定义以下关系:
class B { public: void mf(); }; class D:public B{ ... }; //对于以下调用 D x; B* pb = &x; pb->mf(); D* pd = &x; pd->mf();两者调用的是同一个mf()函数么?其实有可能不是一个。虽然pb和pd都指向了同一个对象。如果D也定义了自己的一份mf()那么就会发生上述情况。因为对于non-virtual的调用都是静态绑定。而虚函数却是动态绑定的。一旦重新定义了继承而来的非虚函数,那么每一个D都是一个B就不为真,违反了is-a的设计原则,并且如果D真的有必要实现与B不同的mf(),那么应该将mf()声明为virtual。
条款37:绝不重新定义继承而来的缺省参数值
由于上一条款绝不重新定义继承而来的non-virtual函数,所以本章讨论将局限于继承一个带有缺省参数值的virtual函数。那么本条款成立的理由十分明确:virtual是动态绑定,而缺省参数却是静态绑定。所以即使派生类重新定义了缺省参数值,参数值也不会表现为多态。解决方法是条款35提出的NVI(non-virtual-interface)手法,将缺省参数放在public非虚函数上,而将虚函数声明为private。
条款38:通过复合塑模出has-a或根据某物实现出
当复合发生于应用域的对象之间,表现出has-a的关系;当它发生于实现域内则是表现出根据某物实现出的关系。......抽象
条款39:明智而审慎的使用private继承
探讨的是private继承,public继承是is-a关系,而private继承纯粹是一种实现技术,意味着只有实现被继承,而接口被略去,即上一条款所说的根据某物实现出的概念。那么什么时候用复合,什么时候用private继承呢?首先我们从类的大小来分析。一个空类或者不含数据成员的类大小通常为1个字节,当使用复合的时候,这个类成员会占用4个字节,因为边界对齐。如果使用private继承,这个类是不占用空间的。另外如果想使用一个类的protected成员,那么必须是private继承了。
over...这一章节算是更完了
相关文章推荐
- 【effective c++】继承与面向对象设计
- 第六章 继承与面向对象设计
- [Effective C++] 继承与面向对象设计
- Effective C++ 6 继承与面向对象设计 学习记录
- 黑马程序员—Java面向对象(单例设计模式、面向对象的继承、final关键字)
- 黑马程序员_学习笔记:4) 面向对象2:继承、this、super、finally、Abstract、模板设计模式、接口
- Javascript乱弹设计模式系列(0) - 面向对象基础以及接口和继承类的实现
- 利用prototype属性自定义对象,实现对象继承等面向对象设计
- 面向对象设计原则七 - 组合优先于继承
- 鸟哥Java学习之单例设计、继承-面向对象
- javascript高级程序设计第六章:面向对象的程序设计——继承读书笔记
- 面向对象设计原则七 - 组合优先于继承
- 面向对象设计三大原则(封装变化点,对接口进行编程,多使用组合而不是继承)
- C++总结之继承和面向对象的设计
- 面向对象设计——继承
- 设计模式学习(一):java 面向对象特征:抽象、封装、多态、继承
- 面向对象设计中的继承、组合、聚合
- 面向对象的设计法则(1)——优先使用(对象)组合,而非(类)继承
- 面向对象设计之五 继承与多态的危险性
- Effective C++面向对象与继承