函数重载(overload)和函数重写(override)
1. 前言:
在C++中有两个非常容易混淆的概念,分别是函数重载(overload)和函数重写(overwirte)。虽然只相差一个字,但是它们两者之间的差别还是非常巨大的。
而通过深入了解这两个概念的区别,会对C++的面向对象机制有一个更深入的理解。
2 函数重载(overload function)
2.1 函数重载的概念:
2.1.1 概念:
当函数具有相同的名称,但是参数列表不相同的情形(包括参数的个数不同或参数的类型不同),这样的同名而不同参数的函数之间,互相被称之为重载函数。
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)除返回值不同外,均有参数类型或参数个数不同的情况,因此构成重载关系。
2.2 函数重载的应用
读者可能会问,既然函数重载这个概念这么拗口,而且有时候又容易和函数重写概念弄混而导致出错,那么为什么在C++里面要有这么一个概念出现呢?
原因其实也很简单,就是因为在一个程序中,会出现很多很多,完成的函数功能完全相同,而仅仅是函数的参数略有不同的情形。这时如果没有函数重载这个概念,那么开发人员恐怕就要为如何为功能完全相同的函数起不同的名而头疼了。

在各种开源的库中,我们也经常可以看到函数重载的身影。比如:
(1)类的构造函数,通常就是函数重载的典型应用。因为一个类通常是可以有很多种构造方式的。 
如QT里面的QString类的构造函数,提供了9种不同的构造函数,这9种构造函数的函数名完全相同,但是它们的参数类型或参数个数却不完全相同,因此是合法的。如图所示:

(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,
所以,只能用函数重写(也就是引出了多态),这样就可以区分和调用子类和父类里重名的函数了。[这里不能用函数重载是因为这里发生在两个类里,而重载不仅仅是在一个类里进行区分]
今天在工作的时候,就是因为在重写基类的某一个虚函数时,由于在复制时把函数的参数类型和基类的参数类型搞得不一致了,导致重写失败。
因此,在调试代码时,本以为程序会进入派生类的重写后的函数中,但是实际却一直进入基类的函数中。最后在网上查询原因时,才恍然大悟,原来是由于自己的失误,而导致了重写失败。
具体是: 
Dx3DActorRotationPanOplayer : public DxBaseOplayer. 
在基类DxBaseOplayer中有一系列的关于响应鼠标事件的虚函数:

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

表面上看起来似乎很像。但是仔细一看,函数的参数是不相同的。
基类的第一个参数类型是:QEvent, 而派生类的第一个参数类型是:QMouseEvent。
正是由于这个参数类型的不同,而导致了派生类实际并没有重写基类的这个成员函数。
因此,在基类的指针调用这个函数时,便无法调用到子类的这个重写函数了。 
只要把派生类的第一个参数类型也修改为QEvent,那么便实现了函数的重写了。
函数重载(overload)和函数重写(override)的更多相关文章
- 重载(overload),覆盖/重写(override),隐藏(hide)
		
写正题之前,先给出几个关键字的中英文对照,重载(overload),覆盖/重写(override),隐藏(hide).在早期的C++书籍中,常常把重载(overload)和覆盖(override)搞错 ...
 - C#  方法重载 overload、方法重写 override、隐藏 new
		
一.重载:同一个作用域内发生(比如一个类里面),定义一系列同名方法,但是方法的参数列表不同.这样才能通过传递不同的参数来决定到底调用哪一个. 值得注意的是,方法重载只有通过参数不同来判断调用哪个方法, ...
 - c++中的重载(Overload)、覆盖(重写,Override) 、隐藏与using声明
		
这些概念有时记住了,但可能没多久就忘了,还是记下来吧.网上找的一篇不错:这里 1 重载与覆盖 成员函数被重载的特征: (1)相同的范围(在同一个类中,不包括继承来的): (2)函数名字相同: (3) ...
 - C++函数重载遇到了函数默认参数情况
		
一.C++中的函数重载 什么是函数重载? 我的理解是: (1)用一个函数名定义不同的函数: (2)函数名和不同参数搭配时函数会有不同的含义: 举例说明: #include <stdio.h> ...
 - C++的函数重载和main函数之外的工作
		
今天被问到一个C++的函数重载问题,一下子没反应过来,这种基础的问题竟然忘记了,以下记录一下这些忘记的内容. 函数重载 函数重载的定义是:在相同的作用域中,如果函数具有相同名字而仅仅是形参表不 ...
 - 方法重载overload与方法重写overwrite
		
方法重载overload: 在同一个类中,出现相同的方法名,与返回值无关,参数列表不同:1参数的个数不同 2参数类型不同 在调用方法时,java虚拟机会通过参数列表来区分不同同名的方法 方法重写ove ...
 - 【C++】多态性(函数重载与虚函数)
		
多态性就是同一符号或名字在不同情况下具有不同解释的现象.多态性有两种表现形式: 编译时多态性:同一对象收到相同的消息却产生不同的函数调用,一般通过函数重载来实现,在编译时就实现了绑定,属于静态绑定. ...
 - java中的重载(overload)和重写(override)区别
		
方法重载(overload): 方法重载就是在一个类中可以创建多个方法,它们具有相同的名字,但是具有不同的参数和不同定义,调用方法时通过传递给他们的不同参数个数和参数列表决定具体使用 哪 ...
 - 函数重载(overload)
		
重载的定义及特点 在同一个类中,允许存在一个以上的同名函数, 只要他们的参数个数或者参数类型不同(不仅指两个重载方法的参数类型不同,还指相同参数拥有不同的参数类型顺序)就构成重载. 重载只和参数列表有 ...
 
随机推荐
- javascript入门教程 (2)
			
这篇我就不铺垫和废话了,我们开始正式进入JS核心语法的学习… 首先我们从基础入手... 一. 基础语法 1.1 区分大小写 JS语法规定变量名是区分大小写的 比如: 变量名 learninpro 和变 ...
 - 关于SQL优化这些你了解吗?
			
目录树 背景 优化点 前提必备知识 优化之一 - 从数据库设计方面考虑 优化之二 - 从SQL语句优化方面考虑 优化之三 - 读写分离与分库分表 背景 在当今这个互联网的时代无非要解决两大难题,其一是 ...
 - ORACLE_HOME_LISTNER is not SET, unable to auto-start Oracle Net Listener
			
执行$ORACLE_HOME/bin/dbstart 启动数据库提示如下: [oracle@prim bin]$ ./dbstart ORACLE_HOME_LISTNER is not SET, u ...
 - oracle之DQL
			
一.单表查询 语法:select * from table where 条件 group by 分组 having 过滤分组 order by 排序 --查询平均工资低于2000的部门的最大工资和平均 ...
 - ios常用数据库、完美无缺
			
直接copy过去就能用,我们不用再去造轮子,现在的xocod9.4更加人性化了,不用再添加依赖库,这点苹果你让我开始喜欢了,哈哈. 需要这兄弟拉进去的哈 下班标的1,2,3,4就是就截图的4个文件,没 ...
 - python初学者日记02(正则表达式)
			
写作时间:2018/12/17 作者:永远的码农(博客园) 一.正则表达式简介: 正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或R ...
 - CSS实现图片等比例缩小不变形
			
<img src="../images/bg1.jpg" alt="" /> img { /*等宽缩小不变形*/ /*width: 100%;*/ ...
 - Linux每日一命令:【00】总纲
			
Linux每日一命令更新频率为每周5篇. 文章结构如下: 简介 语法 选项 参数 常用实例 实用技巧(可选) 参考文档 文章目录如下: 2018-02-19 20:15 -- Linux每日一命令:[ ...
 - C#远程连接postgresql数据库
			
第一次在项目中遇到远程访问postgresql数据库的,当时经常会出现连接数据库的错误,连接字符串出现乱码现象 解决方案 在配置文件中添加连接字符串 <add key="Informa ...
 - 集合之TreeMap
			
TreeMap 底层数据结构是二叉树 如何保证键的唯一: 利用存的特点 如何保证键的可排序: 利用取的特点 左跟右 在map中数据结构只对键有效TreeMap 有Map的键值对的特性:还可以进行排序, ...