Effective C++改善程序与设计的55个具体做法 6. 继承与面向对象设计

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

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

个人理解:基类的函数适用于派生类的每一个函数。

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

derived classes 内的名称会遮掩 base classes 内的名称。在 public 继承下从来没有人希望如此。

为了让被遮掩的名称再见天日,可使用 using 声明式或转交函数( forwarding functions)。

个人理解:相同名称会有覆盖的问题,public 继承可以用using 声明, private函数可以使用转交函数。

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

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

pure virtual 函数只具体指定接口继承。

简朴的(非纯) impure virtual 函数具体指定接口继承及缺省实现继承。

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

个人理解:接口继承只继承函数接口,实现继承继承接口和实现、并且又能够重写;

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

virtual 函数的替代方案包括 NVl 手法及 Strategy 设计模式的多种形式。 NVI 于法自身是一个特殊形式的 Template Method 设计模式.

将机能从成员函数移到 class 外部函数,带来的一个缺点是,非成员函数无法访问 class 的 non-public 成员。

std::function 对象的行为就像→般函数指针。这样的对象可接纳"与给定之目标签名式 (target signature) 兼容"的所有可调用物 (callable entities)。

个人理解:

使用NVI手法,他是用public non-virtual成员函数包裹较低访问性(private和protected)
的virtual函数;

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

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

将继承体系内的virtual函数替换成另一个继承体系内的virtual函数。这是strategy设计模式的传统做法;

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

绝对不要重新定义继承而来的 non-virtual 函数

个人理解:继承类会覆盖基类中函数实现;

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

绝对不要重新定义一个继承而来的缺省参数值,因为缺省参数值都是静态绑定,而virtual函数一一你唯一应该覆写的东西一一却是动态绑定。

个人理解:

class Shape{
public:
	enum ShapeColor {Red, Green, Blue};
	virtual void draw(ShapeColor color=Red) const = 0;
};

class Rectangle : public Shape{
public:
	virtual void draw(ShapeColor color=Green) const;//和父类的默认参数不同
}

Shape* pr = new Rectangle; // 注意此时pr的静态类型是Shape,但是他的动态类型是Rectangle
pr->draw(); //virtual函数是动态绑定,而缺省参数值是静态绑定,**所以会调用Red,而不是green**

class Rectangle : public Shape{
public:
	virtual void draw(ShapeColor color= Red) const; //**(代码重复且带有相依性,不可取)**
}

**//可以更换为NVI的手法可以实现目的**
class Shape{
public:
	enum ShapeColor {Red, Green, Blue};
	void draw(ShapeColor color=Red) const {
		doDraw();
	}
private:
	virtual void doDraw(ShapeColor color) const = 0;
};

class Rectangle : public Shape{
public:
	virtual void doDraw(ShapeColor color) const;
}

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

复合( composition) 的意义和 public 继承完全不同。

在应用域 (application domain) ,复含意味 has -a (有一个)。在实现域(implementation domain) ,复合意味 is-implemented-in-terms-of(根据某物实现出)。

个人理解:

//应用领域:
class Address {...};
class PhoneNumber {...};
class Person {
	...
private:
	std::string name;
	Address address;
	PhoneNumber phone;
} 

//实现域:set并不是一个list,但是set可以has a list:
template<class T>
class Set{
public:
	void insert();
	//.......
private:
	std::list<T> rep;
}

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

Private 继承意味 is-implemented-in-terms of (根据某物实现出)。它通常比复合(composition) 的级别低。但是当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的virtual 函数时,这么设计是合理的。

和复合( composition) 不同, private 继承可以造成 empty base 最优化。这对致力于"对象尺寸最小化"的程序库开发者而言,可能很重要。

个人理解:如果D以private形式继承B,private继承意味着只有实现部分被继承,而没有其他含义。尽可能的使用复合,必要时才使用private(总结中提到的两种情况)

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

多重继承比单一继承复杂。它可能导致新的歧义性,以及对 virtual 继承的需要。

virtual 继承会增加大小、速度、初始化(及赋值)复杂度等等成本。如果 virtual base classes 不带任何数据,将是最具实用价值的情况。

多重继承的确有正当用途。其中一个情节涉及"public 继承某个 Interface class" 和 "private 继承某个协助实现的class" 的两相组合。

个人理解:多重继承基类对象存在多个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值