函数的重载,覆盖/重写,与隐藏

1.  函数重载(Overload):编程

普通的重载咱们都知道是怎么回事。在面向对象的编程中,函数重载只能发生在同一个类当中ide

典型的重载重载就是类的构造函数,好比:无参构造函数,拷贝构造函数,赋值构造函数之间。函数

重载发生的条件是:仅仅函数的形参(数量或者类型)不一样。spa

 

2. 函数覆盖/重写(Override):指针

函数覆盖(也就是重写)就是咱们平时所说的类的多态性实现的时候发生的事情:code

基类指针指向派生类,指针调用函数时派生类的函数就会覆盖基类函数。对象

覆盖发生的条件,就是多态性实现的条件blog

a.基类指针指向派生类;继承

b.基类的函数前有virtual声明为虚函数;接口

c.基类和派生类(函数名和参数等)彻底相同!

 

3. 函数隐藏(Hide?):

其余类定义的函数,被类的同名函数屏蔽,好像被隐藏了。

(说成被覆盖了好像也解释得通,可是人家规定好“覆盖”和“隐藏”的意义了,就入乡随俗好了)

函数隐藏的条件:

a.首先要同名,否则就不是同一个函数了;

b.不一样类的同名函数,假如知足函数覆盖,就会发生函数隐藏!

虽然b听起来很绝对,可是也很好记,关键是正确!

 

4. 举个栗子好了:

 1 class Base
 2 {
 3 public:
 4     virtual  void  f(float  x) { cout  <<  "Base::f(float)"  <<  endl; }
 5     void  g(float  x) { cout  <<  "Base::g(float)"  <<  endl; }
 6     void  h(float  x) { cout  <<  "Base::h(float)"  <<  endl; }            
 7 }
 8 
 9 class Derive
10 {
11 public:
12     virtual  void  f(float  x) { cout  <<  "Derive::f(float)"  <<  endl; }
13     void  g(int  x)     { cout  <<  "Derive::g(int)"  <<  endl; }
14     void  h(float  x)  { cout  <<  "Derive::h(float)"  <<  endl; }            
15 }

调用:
  Base *base = new Derive;
  base -> f(1.0);
  base -> g(2);
  base -> h(1.0);

会发生什么?根据上面的规则很好判断:

先看是否符合多态性的条件,只有Derive::f(float x)符合,因此会发生函数覆盖;

其余不符合的,就是发生函数隐藏,也就是因为指针指向派生类,说此时函数的调用只和派生类有关,和基类没有关系!

 

 

5. 覆盖和隐藏的选择

一间学校,基类是学生,派生类是:小学生,初中生,高中生;

函数有:吃饭,上课,考试;

吃饭是每一个学生都要作的事情,并且作法同样,都是去食堂吃饭;

考试是部分学生(初高中生)须要作的事情,小学生减负不考试;

上课虽然是每类学生都要作的事情,可是每类学生的作法都不相同;

吃饭,考试,上课,对于每一个派生类的共用性程度愈来愈低,这种状况下如何设定函数的模式呢?

 

首先,既然每一个派生类都要实现相同的吃饭函数,就把吃饭放在基类中,做为基类的普通成员函数

派生类继承基类,天然就能够正常使用吃饭函数。

这叫作什么?就是普通的继承啊~

 

而后,上课是每一个派生类都作可是作法都不相同的函数,很容易想到经过多态性实现。

具体来讲就是在基类中声明上课是虚函数,而后在不一样派生类中重写本身的上课函数,进行覆盖。

最好声明上课为纯虚函数,就不用在基类中实现上课函数了,由于基类的上课原本就没有特殊意义,只是一个接口。

这样基类就成了抽象类,不能实例化。

不过不要紧,咱们建议用指针实现类的实例化和函数调用。

 

最后,有大部分派生类可使用考试函数,可是又不能让小学生考试,这种状况下怎么设定函数模式?

确定不能是基类的普通成员函数,不然怎么实现?

第一种方法:

在基类中声明并实现考试函数为虚函数,在大部分派生类中不定义考试函数进行覆盖,

只在小学生类中从新定义一个空的考试函数,进行覆盖以实现多态性

第二种方法:

在基类中定义考试为普通成员函数,派生类经过继承使用她。

对于小学生来讲,能够在类中从新定义一个空的考试函数,实现对基类考试函数的隐藏

 

从逻辑性来讲,实现多态性会更容易理解一些。

相关文章
相关标签/搜索