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

在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函数则指定了继承接口以及一份强制的实现。

万能的函数 之 接口继承 实现继承~~~,布布扣,bubuko.com

时间: 2024-10-10 21:17:47

万能的函数 之 接口继承 实现继承~~~的相关文章

java接口中多继承的问题

java中支撑多继承吗? 支持->接口啊 为什么接口支持多继承呢?因为接口中没有方法体!即使可能两个接口中有一样的抽象方法,但是 只会调用子类中覆盖该同样抽象方法的具体方法!不会引起调用的歧义! interface A{ public abstract void show(); } interface B{ public abstract int show(); } interface C extends A, B{ } /* 相同的函数名,函数参数 但是不同的返回值,继承过来之后就会出现方法定

面向对象程序设计——抽象基类,访问控制与继承,继承中的类作用域,拷贝函数与拷贝控制

一.抽象基类 1)纯虚函数 和普通的虚函数不同,一个纯虚函数无须定义.我们通过在函数体的位置(即在声明语句的分号之前)书写=0就可以将一个虚函数说明为纯虚函数.其中,=0只能出现在类内部的虚函数声明语句处. 值得注意的是,我们也可以为纯虚函数提供定义,不过函数体必须定义在类的外部.也就是说,我们不能在类的内部为一个=0的函数提供函数体. 2)含有纯虚函数的类是抽象基类 含有(或者未经覆盖直接继承)纯虚函数的类是抽象基类.抽象基类负责定义接口,而后续的其他类可以覆盖该接口.我们不能直接创建一个抽象

接口多继承自接口和接口是否可以继承自一般类的疑问?

接口是常量值和方法定义的集合.接口是一种特殊的抽象类. Java类是单继承的.classB Extends classA java接口可以多继承.Interface3 Extends Interface0, Interface1, interface-- 不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢? 但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口. 注意: 1)一个类如果实现了一个接口,则要实现该接口

Java集合中的接口实现与继承

很多人都对接口以及抽象实现类认识混乱 ,注意区分实现接口与继承的区别,图中深色为接口,浅色为实现类,extend为继承,implements为接口实现 List与Set接口继承自Collection接口 LinkedList是继承自AbstractSequentialList(抽象类,实现了List接口) ArrayList与Vector是继承自AbstractList(抽象类,实现了List接口) AbstractSet是实现了Set接口的,本身是一个抽象类.继承自AbstractCollec

Java中接口是否可以继承多个接口?

可以. 接口是常量值和方法定义的集合.接口是一种特殊的抽象类. java类是单继承的.classB Extends classA java接口可以多继承.Interface3 Extends Interface0, Interface1, interface…… 不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢? 但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口. 注意: 1)一个类如果实现了一个接口,则要实

C#虚函数和接口的区别

接口只能声明不能实现,虚函数可以. 接口:对外提供可以访问的函数叫接口.虚函数不需要被强制重写,其本身含有实现部分. 抽象类:指派了派生类必须实现的函数(纯虚函数),不然编译不通过. 虚函数的限制:    1.虚函数仅适用于有继承关系的类对象,   所以只有类的成员函数才能说明为虚函数.      2.静态成员函数不能是虚函数.      3.内联函数不能是虚函数.      4构造函数不能是虚函数.      5.析构函数可以是虚函数. 接口可以有静态成员.嵌套类型.抽象.虚拟成员.属性和事件

web前端开发必懂之一:JS继承和继承基础总结

首先,推荐一篇博客豪情的博客JS提高篇: http://www.cnblogs.com/jikey/p/3604459.html ,里面的链接全是精华, 一般人我不告诉他; 我们会先从JS的基本的设计模式开始,由浅入深: 工厂模式:因为使用用一个接口创建很多对象会产生大量的重复代码,为了解决这个问题,人们就开始使用工厂模式: <!DOCTYPE html> <html> <head> <title></title> <meta charse

C#面向对象(OOP)入门—第二天—多态和继承(继承)

介绍: 第一天的内容主要是不同情形下的方法重载.这一部分则主要讲面向对象中继承的概念.首先用一个要点图形来定义继承. 继承 一个简单的例子: ClassA: class ClassA:ClassB { public void Display1() { Console.WriteLine("ClassA Display1"); base.Display1(); } } ClassB: class ClassB { public int x = 100; public void Displ

C++ 虚函数&amp;纯虚函数&amp;抽象类&amp;接口&amp;虚基类(转)

http://www.cnblogs.com/fly1988happy/archive/2012/09/25/2701237.html 1. 多态 在面向对象语言中,接口的多种不同实现方式即为多态.多态是指,用父类的指针指向子类的实例(对象),然后通过父类的指针调用实际子类的成员函数. 多态性就是允许将子类类型的指针赋值给父类类型的指针,多态是通过虚函数实现的. 多态可以让父类的指针有“多种形态”,这是一种泛型技术.(所谓泛型技术,就是试图使用不变的代码来实现可变的算法). 2. 虚函数 2.1