首页 > 代码库 > Effective C++ Item 34 区分接口继承与实现继承

Effective C++ Item 34 区分接口继承与实现继承

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie


关联条款 Item 36


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

class Shape{
public:
	virtual void draw() const = 0;
	virtual void error(const std::string &msg);
	int objectID() const;
	//...
};


class Rectangle: public Shape{...};
class Ellipse: public Shape{...};

1.pure virtual 函数 --> 让 derived classes 只继承函数接口。
Shape::draw 的声明式仍是对具体 derived classes 设计者说, “你必须提供一个 draw 函数,但我不干涉你怎么实现它”

2.impure virtual 函数 --> 让 derived classes 继承该函数的接口和缺省实现
Shape::error 的声明式告诉 derived classes 设计者说, “你必须支持一个 error 函数,但如果你不想自己写一个,可以使用 Shape要提供的缺省版本”

3.non-virtual 函数 --> 让 derived classes 继承函数的接口及一份强制性实现

class 设计常犯两个错误
1.将所有函数声明为 non-virtual
Item 7:为多态基类声明 virtual 析构函数
2.将所有成员函数声明为 virtual

经验: impure virtual 函数同时指定函数声明和函数缺省行为,可能造成危险。。
示例:
class AirPort{...};
class AirPlane{
public:
	virtual void fly(const AirPort &destination);
	//...
};
void AirPort::fly(const AirPort &destination){
	//缺省代码,将飞机飞至指定的目的地
}
class ModelA: public AirPlane {...};
class ModelB: public AirPlane {...};


class ModelC: public AirPlane {
	... // 未声明 fly 函数, 但C型飞机的飞行方式与A,B不同。
};


AirPort PDX(...);
AirPlane *pa = new ModelC;
//...
pa->fly(PDX); //调用 AirPlane::fly

解析:
这个程序试图以 ModelA, ModelB 的飞行方式来飞 ModelC

纠正:
切断“virtual 函数接口” 和 其“缺省实现” 之间的连接。将 AirPlane::fly 改为一个 pure virtual 函数,只提供飞行接口,
另以独立函数 defaultFly 提供缺省实现。

class AirPlane{
public:
	virtual void fly(const AirPort &destination) = 0;
	//...
protected: // protected 因为客户端不需要在意飞机能不能飞
	void defaultFly(const AirPort &destination); //Item 36
};


void AirPlane::defaultFly(const AirPlane &destination){
	//缺省代码,将飞机飞至指定的目的地
}


class ModelA: public AirPlane{
public:
	virtual void fly(const AirPort &destination){
		defaultFly(destination);
	}
	//...
};


class ModelB: public AirPlane{
public:
	virtual void fly(const AirPort &destination){
		defaultFly(destination);
	}
	//...
};


class ModelC: public AirPlane{
public:
	virtual void fly(const AirPort &destination);
	//...
};


void ModelC::fly(const AirPort &destination){ // pure virtual 函数迫使  ModelC 必须提供自己的 fly 版本
	//...
}

纠正2:我更喜欢这个,没那么多变量名
class AirPlane{
public:
	virtual void fly(const AirPort &destination) = 0;
	//...
protected: // protected 因为客户端不需要在意飞机能不能飞
	void defaultFly(const AirPort &destination); //Item 36
};


void AirPlane::fly(const AirPlane &destination){ //pure virtual 函数实现
	//缺省代码,将飞机飞至指定的目的地
}


class ModelA: public AirPlane{
public:
	virtual void fly(const AirPort &destination){
		AirPlane::fly(destination);
	}
	//...
};


class ModelB: public AirPlane{
public:
	virtual void fly(const AirPort &destination){
		AirPlane::fly(destination);
	}
	//...
};


class ModelC: public AirPlane{
public:
	virtual void fly(const AirPort &destination);
	//...
};


void ModelC::fly(const AirPort &destination){ // pure virtual 函数迫使  ModelC 必须提供自己的 fly 版本
	//...
}