函数重载(overload)和函数重写(override)

1. 前言:

  在C++中有两个很是容易混淆的概念,分别是函数重载(overload)和函数重写(overwirte)。虽然只相差一个字,可是它们二者之间的差异仍是很是巨大的。编程

  而经过深刻了解这两个概念的区别,会对C++的面向对象机制有一个更深刻的理解。数组

2 函数重载(overload function)

2.1 函数重载的概念:

2.1.1 概念:

当函数具备相同的名称,可是参数列表不相同的情形(包括参数的个数不一样或参数的类型不一样),这样的同名而不一样参数的函数之间,互相被称之为重载函数。ide

2.1.2 基本条件:

  • 函数名必须相同;
  • 函数参数必须不相同,能够是参数类型或者参数个数不一样;
  • 函数返回值能够相同,也能够不相同。(备注:可是若是函数的名称和参数彻底相同,仅仅是返回值类型不一样,是没法进行函数重载的。

2.1.3 注意:

  • 只能经过不一样的参数样式进行重载,例如:不一样的参数类型,不一样的参数个数,或者不一样的参数顺序
  • 不能经过访问权限、返回类型、抛出的异常不一样而进行重载;
  • 重载的函数应该在相同的做用域下。

2.1.4 函数重载实例判断:

如下的集中写法,分别表示了哪些是重载的,哪些不是重载的。 
(1) void func1( int arg1); 
(2) void func1( double arg1); 
(3) void func1( int arg1, int arg2); 
(4) bool func1(int arg1, double arg2) 
(5) int func1(int arg1);函数

在上述的5个函数中,函数名称都是func1,彻底相同;可是: 
(2)与(1)的参数个数相同,参数类型不一样,构成重载; 
(3)与(1)和(2)的参数个数不一样,构成重载; 
(4)与(1)和(2)的参数个数不一样,与(3)的参数个数相同,可是第二个参数类型不一样,构成重载; 
(5)与(1)的参数个数和参数类型均相同,仅返回值的类型不相同,不构成重载;可是(5)与(2),(3)和(4)除返回值不一样外,均有参数类型或参数个数不一样的状况,所以构成重载关系。spa

 

2.2 函数重载的应用

读者可能会问,既然函数重载这个概念这么拗口,并且有时候又容易和函数重写概念弄混而致使出错,那么为何在C++里面要有这么一个概念出现呢?指针

缘由其实也很简单,就是由于在一个程序中,会出现不少不少,完成的函数功能彻底相同,而仅仅是函数的参数略有不一样的情形。这时若是没有函数重载这个概念,那么开发人员恐怕就要为如何为功能彻底相同的函数起不一样的名而头疼了。调试

 

在各类开源的库中,咱们也常常能够看到函数重载的身影。好比:对象

(1)类的构造函数,一般就是函数重载的典型应用。由于一个类一般是能够有不少种构造方式的。 
如QT里面的QString类的构造函数,提供了9种不一样的构造函数,这9种构造函数的函数名彻底相同,可是它们的参数类型或参数个数却不彻底相同,所以是合法的。如图所示: blog

(2)类的成员函数,如赋值函数等。 
如VTK的vtkImageData类的两个成员函数就是重载的。如: 继承

 

 

这两个成员函数的函数名称都是SetDimensions(),可是第一个函数的参数是3个int型的值;另外一个函数的参数是一个const int型的数组,返回值都是void。这样也是能够构成函数重载的。

在安装有编程助手的状况下编写代码时,若是遇到一个类的成员函数有重载时,助手一般会提示开发者,要选择哪个重载函数。以下图所示。vtkImageData的SetDimensions()函数有两个重载形式,所以在编写代码时,助手会提示2 of 2,表示这是2个重载函数中的第二个,点击能够切换到第一个重载函数。开发者须要根据上下文的要求,来选择相应的重载函数进行编写。

 


 

 

3 函数重写(override function)

虽然与函数重载仅仅只有一个字的差异,可是这两个概念倒是相差了很远很远。它俩彷佛一点关系都没有。也正由于如此,这个很是考验C++语言的基本功,也是历年C++笔试中常常会出现的考题。

3.1 函数重写(override function)

3.1.1 概念:

函数重写,也被称为覆盖,是指类从新定义父类中有相同名称和参数的虚函数,主要在继承关系中出现

3.1.2 基本条件:

  • 重写的函数和被重写的函数必须都为virtual函数,并分别位于基类和派生类中;
  • 重写的函数和被重写的函数,函数名和函数参数必须彻底一致
  • 重写的函数和被重写的函数,返回值相同,或者返回指针或引用,而且派生类虚函数返回的指针或引用的类型基类中被替换的虚函数返回的指针或引用的类型或者其子类型(派生类型)。

3.2 函数重写的应用

有个规则是赋值兼容性原则,而这个规则有bug,当子类和父类的函数重名的时候,不论是基类的对象去指向/引用子类对象,都是调用基类的函数,而和子类无关,这明显是一个bug,

因此,只能用函数重写(也就是引出了多态),这样就能够区分和调用子类和父类里重名的函数了。[这里不能用函数重载是由于这里发生在两个类里,而重载不只仅是在一个类里进行区分]

 PS: 重写/多态是类的特性,而重载不是,在全局函数里也能够用重载
 

今天在工做的时候,就是由于在重写基类的某一个虚函数时,因为在复制时把函数的参数类型和基类的参数类型搞得不一致了,致使重写失败。

所以,在调试代码时,本觉得程序会进入派生类的重写后的函数中,可是实际却一直进入基类的函数中。最后在网上查询缘由时,才恍然大悟,原来是因为本身的失误,而致使了重写失败。

具体是: 
Dx3DActorRotationPanOplayer : public DxBaseOplayer. 
在基类DxBaseOplayer中有一系列的关于响应鼠标事件的虚函数: 

 

其中,在派生类中我想从新实现其中的一个虚函数 OnMouseLeave()。 
可是,我在子类定义该函数时,却写成了: 

 

表面上看起来彷佛很像。可是仔细一看,函数的参数是不相同的。 

基类的第一个参数类型是:QEvent, 而派生类的第一个参数类型是:QMouseEvent。

正是因为这个参数类型的不一样,而致使了派生类实际并无重写基类的这个成员函数

 

所以,在基类的指针调用这个函数时,便没法调用到子类的这个重写函数了。 只要把派生类的第一个参数类型也修改成QEvent,那么便实现了函数的重写了。

相关文章
相关标签/搜索