Effective C++ 第六章:继承与面向对象设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/budding0828/article/details/86624958

第六章:继承与面向对象设计

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

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

  • 基类函数被子类函数所覆盖:
class Base{
private:
	int x;
public:
	virtual void f1() = 0;
	virtual void f1(int);
	virtual void f2();
	void f3();
	void f3(double);
	...
}
class Derived: public Base{
public:
	virtual void f1();
	void f3();
	void f4();
}
Derived d;
int x;
...
d.f1();	 //没问题,调用Derived::f1();
d.f1(x);    //错误,因为Derived::f1遮掩了Base::f1
d.f2();	 //没问题,调用Base::f2()
d.f3();	 //没问题,调用Derived::f3
d.f3(x);	//错误,因为Derived::f3遮掩了Base::f3
  • 解决方案:使用using声明
class Derived: public Base{
public:
	using Base::f1;
	using Base::f3;
	virtual void f1();
	void f3();
	void f4();
}
//这样子在调用的时候,会先在子类的函数中寻找合适的,如果没有,则会在基类中寻找。

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

class Shape{
public:
	virtual void draw() const = 0;
	virtual void error(const striing& msg);
	int objectID() const;
	...
};
  • 声明一个pure virtual函数的目的是为了让derived class只继承函数接口。如:
    virtual void draw() const = 0;

  • 声明简朴的(非纯)impure virtual函数的目的。是让derived classes继承该函数的接口和缺省实现。如:
    virtual void error(const striing& msg);
    如果你不想实现自己的版本,那么也可以使用Base提供的缺省版本。

  • 声明non-virtual函数的目的是为了令derived classes继承函数的接口及一份强制实现。这种函数绝不该在derived class中被重新定义

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

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

  • 静态绑定:由指针的性质决定调用版本
class B{
public:
	void mf();
	...
};
class D: public B{
public:
	void mf();
	...
};
//
D x;
B* pb = &x;
pb->mf();	//调用B::mf
D* pd = &x;
pd->mf();	//调用D::mf
  • 动态绑定:virtual 函数
    无论是使用pb还是pd,真正指向的都是一个类型为D的对象。所以都会调用D::mf

条款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 drwa(ShapeColor color = Green) const;
};
Shape* ps = new Rectangle;
ps->drwa();  //此时缺省参数是Red

缺省参数值来自Shape class而非Rectangle class!

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

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

  • private继承意味只有实现部分被继承,接口部分应略去。如果D以private形式继承B,意思是D对象根据B对象实现而得。

  • 尽可能使用复合,必要时才使用private继承。

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

class Empty{}; //会占用一定空间,如一个char大小

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

  • virtual的代价:virtual 继承的那些classed所产生的对象往往比使用non-virtual继承的class体积要大,并且访问virtual base classed的成员函数变量时,也比访问non-virtual base classed的成员变量速度慢。

  • virtual base classes 使用技巧:

    • 非必要不是用virtual bases,平常使用non-virtual继承
    • 如果必须使用,尽可能避免在其中放置数据
  • 多重继承会导致歧义。其使用场景之一是:public继承某个Interface class 和 private 继承某个协助实现的class的两相结合。

猜你喜欢

转载自blog.csdn.net/budding0828/article/details/86624958