首页 > 代码库 > 万能的函数 之 接口继承 实现继承~~~

万能的函数 之 接口继承 实现继承~~~

在public继承中,(public 继承表示的关系是 “is  a ” 的关系),其类中定义的函数主要有三类:pure virtual函数,impure virtual函数以及non-virtual函数,这三种函数决定了public继承中的两个重要概念 : “ 函数接口继承” 以及 “函数实现继承”。那么接下来将针对这样一个不简单的问题做一些简介。


考虑如下的类定义:

class Shape{

public:

   virtual void show() const = 0;

   virtual void error(const string &) ;

   int getID() const;

  ....

};

class Rectangular : public Shape { ...  };

class Ellipse : public Shape { ... } ;


对于上述类,首先做一些简单的说明:

Shape是抽象类,因为其中含有纯虚函数( show函数 ), 抽象类不能定义对象,值得注意的是,虽然show函数是纯虚函数,但是并不表示Shape不可以为其定义函数体。Shape可以为show函数定义函数体,但是对该函数的调用显然不能由对象来调用(因为Shape不能定义对象),因此只能 Shape::show() ;来调用。


接下来,就是重要的部分了。


身为class的设计者,有时候希望derived class只继承基类的成员函数的接口,有时候又需要同时继承函数的接口以及实现,有时候又需要重写它们所继承的实现,有时候又希望derived同时继承接口与实现,并且不允许重写。


这些复杂的关系,接下来根据上述类的定义一步一步的解析:


Shape的成员函数的接口总是被继承。 由于 public 继承的 “is a   ” 关系,也就是说任何可以施加到base class上的行为都可以施加到derived class身上。至于derived class如何使用他们,这便与 上述3种 virtual 函数有关。


首先,pure  virtual 纯虚函数。 它必须被任何继承了它的class重新生命,并且定义,因为他们在抽象class类通常没有定义(只是通常,原因见上)。


  1  声明pure  virtual  函数  是为了让derived class继承它的接口(也没有函数体可以继承 啊~~)。只是告诉 derived class自行去去定义自己的实现。

  2   声明impure virtual函数 是为了让derived class继承它的接口以及缺省实现(当然derived class也可以自己重新实现,多态~~)

但是,这样会遇到问题,如果新添加的derived class忘记定义自己的impure virtual函数体,也就意味着它直接使用base class的定义,这可能违背本身derived class的操作,造成意想不到的结果。对于这种问题,我们可以使用   pure  virtual   + default action来完成。例如下面的代码:


class Airplane
{
public:
	virtual void fly(string &destination); //虚函数,发出飞机飞行的目的地的指令
	...

};
class SecA : public Airplane { ... } ; //SecA 与 SecB直接使用的base class的默认fly定义
class SecB : public Airplane { ... } ;

//先新添加一条航线SecC,但是忘记定义了的fly函数指定目的地,因此C航线,依旧飞的是原来的路线,这恐怕不是你想要的吧。
class SecC : public Airplane {...}; 

因此,使用  pure  virtual   + default action来改进,有:

class Airplane
{
public:
	virtual void fly(string &destination) = 0; //纯虚函数,由各个航线自己指定目的地
	...
protected:
	void defaultFly(const string &destination);
 

};
void Airplane :: defaultFly (const string &destination))
{
	//default fly strategy
} 

//SecA 与 SecB自行实现fly函数决定目的地。
class SecA : public Airplane 
{
	virtual void fly(string &destination) 
	{
		Airplane::defaultFly(destination);
	}
     ...
} ; 

class SecB : public Airplane 
{
	virtual void fly(string &destination) 
	{
		Airplane::defaultFly(destination);
	}
...
} ; 


现在新添加的SecC航线,就必须自己定义fly函数了。
值得注意的是:上面的defaultFly函数是non-virtual的,因为没有任何函数需要重新定义它~~
试想,如果 defaultFly 函数是virtual的,那么某些类忘记定义了怎么办,额~~好熟悉的话,又得循环回去了~~



注意,在上面提到过pure virtual函数也是可以有定义体的,那么我们就可以不用声明 defaultFly 函数了,实现接下来的部分:

class Airplane
{
public:
	virtual void fly(string &destination) = 0; //纯虚函数,由各个航线自己指定目的地
	...
};

void Airplane :: fly (string &destination))
{
	//default fly strategy
} 

//SecA 与 SecB自行实现fly函数决定目的地。
class SecA : public Airplane 
{
	virtual void fly(string &destination) 
	{
		Airplane::fly(destination); //通过类名调用纯虚函数的实现
	}
     ...
} ; 

class SecB : public Airplane 
{
	virtual void fly(string &destination) 
	{
		Airplane::fly(destination);
	}
...
} ; 


最后,是那个non-virtual的函数,很简单,derived class 不能重新定义,只能无条件的继承该函数的接口与实现。


综上所述:定义virtual (pure / impure)以及non-virtual 是取决于类的设计者的意图:


在public 继承下,derived class 总是继承base class的全部接口。

pure virtual函数只指定了继承的接口。

impure virtual函数指定了继承接口以及一份缺省实现。

non-virtual函数则指定了继承接口以及一份强制的实现。