转自:http://www.cnblogs.com/j2eee/archive/2006/09/22/511954.html

函数重载
如何讲函数重载:
What——函数重载是什么?

why——为什么要用函数重载,没有函数重载会怎样?

how——举例说明怎么使用函数重载

*******************************************************************************
   能使名字方便使用,是任何程序设计语言的一个重要特征。
   当 我们创建一个对象(即变量)时,要为这个存储区取一个名字。一个函数就是一个操作的名字。正是靠系统描述各种各样的名字,我们才能写出易于人们理解和修改 的程序。象写文章一样,目的在于如何同读者交流。这里就产生了这样一个问题:如何把人类自然语言的有细微差别的概念映射到编程语言中。
通常,自 然语言中同一个词可以代表许多种不同的含义,这要依赖上下文来确定。这就是所谓的一词多义,从编程的角度来说就是该词被重载了。所谓重载,从词义上说就是 重新载入,用句俗话说就是“换汤不换药”。要学会试着理解这一点,这点非常有用,特别是对于细微的差别。具个例子:
   我们可以说“喝可乐,喝酒”。如果非得说成“喝(喝可乐的喝)可乐,喝酒(喝酒的喝)酒”,那将是很愚蠢的,就好像听话的人对指定的动作毫无辨别能力一样。管他和的么事,总不是让液体进入你的体内,至于么样喝,喝了以后起么样的反应,那就是后话了。
然 而大多数编程语言要求我们为每个函数设定一个唯一的标识符。如果我们想打印三种不同类型的数据:整型、字符型和实型,我们通常不得不用三个不同的函数名, 如p r i n t _ i n t ( )、p r i n t _ c h a r ( )和p r i n t _ f l o a t ( ) ,这些既增加了我们的编程工作量,也给读者理解程序增加了困难。举个吃饭的例子,你桌子上面有三盘菜,你吃第一盘菜要用金筷子,第二盘,要用银筷子,第三 盘要用象牙筷子一样,几麻烦,用个方便筷子不是一样的吃了。
   说白了,那双方便筷子就是一个函数重载的实例。
   在C + +中,还有另外一个原因需要对函数名重载:构造函数。因为构造函数的名字预先由类的名字确定,所以只能有一个构造函数名。但如果我们想用几种方法来创建一 个对象时该怎么办呢?例如创建一个类,它可以用标准的方法初始化,也可以从文件中读取信息来初始化,我们就需要两个构造函数,一个不带参数(缺省构造函 数),另一个带一个字符串作为参数,以表示用于初始化对象的文件的名字。(例子:两双方便筷子,一双是新的刚那出来的,另一个是高温消毒好了的!但都是方 便筷子。)所以函数重载的本质就是允许函数同名。在这种情况下,构造函数是以不同的参数类型被调用的。
重载不仅对构造函数来说是必须的,对其他函数也提供了很大的方便,包括非成员函数。
另外,函数重载意味着,我们有两个库,它们都有一个同名的函数,只要它们的参数不同就不会发生冲突。
   我这里讲的主题不是函数重载,而是让大家如何方便是使用“筷子”(函数名)去取用餐桌上的“美味食物”(调用函数)!
函 数重载允许多个函数同名(象多种形式的筷子一样),但还有另一种方法使函数调用更方便。如果我们想以不同的方法(象很多不同的手法那筷子一样,左手拿,右 手拿)调用同一函数,该怎么办呢?当函数有一个长长的参数列表,而大多数参数每次调用都一样时,书写这样的函数调用会使人厌烦,程序可读性也差。C + +中有一个很通用的作法叫缺省参数。缺省参数就是在用户调用一个函数时没有指定参数值而由编译器插入参数值的参数。(象吃了饭,筷子碗一丢,不想洗碗筷, 让你父母来洗一样。)
这样f (“h e l l o”) , f (“h i”, 1 )和f (“h o w d y”, 2 ,‘c’)可以用来调用同一函数。它们也可能是调用三个已重载的函数,但当参数列表相同时,我们通常希望调用同一函数来完成相同的操作。

关于函数重载更深层的说明(编译器)
void print(char);
void print(float);
   无论这两个函数是某个类的成员函数还是全局函数都无关紧要。如果编译器只使用函数名字的范围,编译器并不能产生单一的内部标识符,这两种情况下都得用_ p r i n t结尾。(就象一双方便筷子,光看握筷子的手,我们谁都不晓得他夹了什么菜。)
   重 载函数虽然可以让我们有同名的函数,但这些函数的参数列表应该不一样。所以,为了让重载函数正确工作,编译器要用函数名来区分参数类型名。上面的两个在全 局范围定义的函数,可能会产生类似于_ p r i n t _ c h a r和_ p r i n t _ f l o a t的内部名。(看到他夹了么菜了)
   因为,为这样的名字分解规定一个统一的标准毫无意义,所以不同的编译器可能会产生不同的内部名。

重 载的函数与具有多态性的函数(即虚函数)不同处在于:调用正确的被重载函数实体是在编译期间就被决定了的;而对于具有多态性的函数来说,是通过运行期间的 动态绑定来调用我们想调用的那个函数实体。多态性是通过重定义(或重写)这种方式达成的。请不要被重载(overloading)和重写 (overriding)所迷惑。重载是发生在两个或者是更多的函数具有相同的名字的情况下。区分它们的办法是通过检测它们的参数个数或者类型来实现的。
*********************************************************
虚函数
什么是虚函数???
   虚函数是指一个类中你希望重载的成员函数,当你用一个基类指针或引用指向一个继承类对象的时候,你调用一个虚函数,实际调用的是继承类的版本。
                                                     ——摘自MSDN
什么是多态???
   多态是面向对象程序设计和面向过程程序设计的主要区别之一,何谓多态?一名俗话说:“龙生九子,子子不同”多态就是同一个处理手段可以用来处理多种不同的情况。
   这里我们主要讨论虚函数的格式、条件(什么样的函数才叫虚函数)、调用虚函数时的注意事项。

虚函数是成员函数,而且是非static的成员函数。说明虚函数的方法如下:
virtual <类型说明符><函数名>(<参数表>)
其中,被关键字virtual说明的函数称为虚函数。
   如 果某类中的一个成员函数被说明为虚函数,这就意味着该成员函数在派生类中可能有不同的实现。(例:一句俗话就是“聋子的耳朵——摆设”,就象一个残疾人 士,可能他听不见,但不代表他儿子听不见,我们一般把基类叫做“父类”,派生类叫做“子类”。但我们不能说“龙生龙,凤生风,老鼠生儿会打洞”啊!他老爸 的耳朵是摆设,但在儿子这里就是接受信息的器官了。)
     (1) 与基类的虚函数有相同的参数个数;
     (2) 其参数的类型与基类的虚函数的对应参数类型相同;
     (3) 其返回值或者与基类虚函数的相同,或者都返回指针或引用,并且派生类虚函数所返回的指针或引用的基类型是基类中被替换的虚函数所返回的指针或引用的基类型的子类型。(就像他老爹不识字,但是他可以让他读大学的儿子来带他看信,读报一样)
   一般要求基类中说明了虚函数后,派生类说明的虚函数应该与基类中虚函数的参数个数相等,对应参数的类型相同,如果不相同,则将派生类虚函数的参数的类型强制转换为基类中虚函数的参数类型。

抽象类

带有纯虚函数的类称为抽象类。抽象类是一种特殊的类,它是为了抽象和设计的目的而建立的,它处于继承层次结构的较上层。抽象类是不能定义对象的,在实际中为了强调一个类是抽象类,可将该类的构造函数说明为保护的访问控制权限。
   抽象类的主要作用是将有关的组织在一个继承层次结构中,由它来为它们提供一个公共的根,相关的子类是从这个根派生出来的。(例:就是一个手机模具)
   抽象类刻画了一组子类的操作接口的通用语义,这些语义也传给子类。一般而言,抽象类只描述这组子类共同的操作接口,而完整的实现留给子类。
   抽 象类只能作为基类来使用,其纯虚函数的实现由派生类给出。如果派生类没有重新定义纯虚函数,而派生类只是继承基类的纯虚函数,则这个派生类仍然还是一个抽 象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体类了。

一个实例:
class 人()
{public :
//......
void 吃()
{人吃饭;
}
//......
char *Name;
int age;
};

class 狗()
{public :
//......
void 吃()
{狗吃屎;
}
//......
char *Name;
int age;
};
   人类、狗类有一些相同的东东,如名字,年纪,吃的动作等,有人想到了为了代码的重用,让人类继承狗类,可是数据的冗余让这个想法完蛋了,所以有人又想出可不可以定义一个这样的类:

这个类界于人类狗类之间,有人类和狗类共有的一些东东,比如年纪,名字,体重什么的,但它是不存在实例的,它的存在意义也是只是为了派生其它类,如人类、狗类,这样可以使系统清淅、。。。。。、、反正好处多多。

在这个世界上根本不存在界于人狗之间的东东,所以这个“人狗之间类”中的“吃”也是没什么意义,你也很难为它的内容下个定义,况且也没必要,所以定义它为纯虚函数,形式为:virtual void 吃()=0; 用来告诉系统:
1、这个函数可以没有函数定义;
2、拥有本函数的类是抽象类;
你可能会说,即然纯虚函数没什么意义,为什么还要它,它的作用是什么呢?
为实现多态作准备!!!

虚函数的作用:
之一: 虚实同型
之二: 相伴永远
之三: 有则用之,无则虚之

关于二义性的单独说明:
  什 么是二义性?从字面上来说就是产生的歧义,为什么会产生歧义?这里我举个例子:象你到商店去买烟,都是黄鹤楼,有150,24,18三个价位的,都是烟, 也就是说烟是他们的基类,而你要买哪包抽呢?跟跟老板将:“拿包黄鹤楼!”他哪知道你买多少钱的烟?这里就产生了二义性!同时也引出了二义性的解决方法! 老板就会问你:“买多少钱一包的!”这里你就可以做选择了!但是编译器不会开口问你调用哪个父类的成员函数!所以你要事先说明!(y::gety())

总结:
用 个例子字来总结,函数重载,是静态的多态(静态联编),你可以想象成为,你去餐馆吃饭,吃着不同的菜(不同数量,不同类型的参数),用的是同一双筷子(函 数名),自己动手吃,不能指使别人帮你实现功能(自己动手,风记足食)。而虚函数,是动态的多态(动态联编),你则可以想象为,你要么是儿孙满堂的老人或 者是有钱的款爷,到饭店吃大餐,自己不动手,而且吃得很讲究,不同的食物要用不同的餐具(不同的对象),而且是使唤别人(子类成员函数实现功能)喂你吃。 你只要指使一下(基类指针或引用指向)就OK了。在别人看来,你也是在吃饭(具有相应的功能),但是你根本没有动手,都是要手下的小弟搞定(子类成员函数 实现功能)。

重载、重定义、虚函数相关推荐

  1. printf函数 重定义printf函数。

    printf 的宏定义版本 前言: 我们在写程序的时候,总是或多或少会加入一些printf之类的语句用于输出调试信息,但是printf语句有个很不方便的地方就是当我们需要发布程序的时候要一条一条的把这 ...

  2. 11 虚函数【C++】

    11- 判断题 1-1 虚函数是用virtual 关键字说明的成员函数. T 1-2 动态绑定是在运行时选定调用的成员函数的. T 1-3 构造函数可以声明为虚函数.F 1-4 构造函数可以声明为纯虚 ...

  3. C++虚函数和纯虚函数理解

    虚函数:函数中带有关键字virtual 纯虚函数:纯虚函数是在基类中申明为虚函数,它在基类中没有定义, 但是要求任何派生类都需要定义自己的实现方法,在基类的实现纯虚函数的方法是在函数原型后添加=0(v ...

  4. C++多态与虚函数的实现

    文章目录 多态 问题抛出 面向对象新需求 多态的意义探究 面向对象三大概念: 多态成立的三要素: 虚析构 函数的重载.重写.重定义 函数重载 函数重定义 虚函数重写 纯虚函数和抽象类 纯虚函数 抽象类 ...

  5. c/c++开发,无可避免的自定义类类型(篇三).类与虚函数

    深入而全面了解virtual虚函数与类设计关系 目录 一.virtual 函数说明符的作用 二.virtual 成员函数与普通成员函数 三.不必每个派生类重定义virtual 函数 四.派生类可以兼顾 ...

  6. c++中的多态---1(多态概念,静态联编和动态联编,多态原理解析,重载,重写,重定义的对比)

    多态的基本概念 多态是面向对象设计语言数据抽象和继承之外的第三个基本特征 多态性(polymorphism)提供接口与具体实现之间的另一层隔膜,从而将"what"和"ho ...

  7. C/C++基础语法复习(三):C++重载函数,多态,虚函数

    1.重载运算符和重载函数: C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载. 重载声明是指一个与之前已经在该作用域内声明过的函数或方法具有相同名称的声明,但是它 ...

  8. C++多态(一)——多态的定义、虚函数、静态绑定和动态绑定

    本篇涉及内容: 多态的定义 虚函数 静态绑定和动态绑定 多态的定义: 多态分为两类 静态多态:在同一个类中,函数重载和运算符重载都属于静态多态,即函数在相同的函数名情况下,存在着不同的状态,体现了多态 ...

  9. 虚函数 2 之虚函数的定义

    1.虚函数的定义 虚函数就是在基类中被关键字 virtual 说明,并在派生类中重新定义的函数. 虚函数的作用是允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类中的 ...

  10. 坚持学习100天:多态(函数重载、虚函数和多态)

    前言 Hello,我是修齊. 学习C++的第一百零一十天,将近五一假期了,不浪漫亦是罪名,男生今年不能再挨批斗了,放假就得好好陪陪身边的人浪漫浪漫,生活,加油,学习加油. 在这里记录一些学习的东西和学 ...

最新文章

  1. docker安装并运行elasticsearch
  2. java基础知识讲解(一)数据类型和运算符
  3. Python函数式编程简介(一)高阶函数
  4. java nio 面试题_10个最高频的Java NIO面试题剖析!
  5. IDEA 编译构建等工程配置
  6. 【排序算法】冒泡排序(C语言)
  7. Windows7 品牌机OEM原版光盘镜像下载大全
  8. 创新工场和海豚浏览器宣讲会启示
  9. 如何从课堂派上扒取直播视频
  10. leetcode 36. 有效的数独 (将 9 * 9 数独划分成 9 宫格 )
  11. php 钉钉头像生成,从零开始打造专属钉钉机器人
  12. 夏普Sharp AR-M207 一体机驱动
  13. NameError: name ‘XXX‘ is not defined
  14. JAVA处理Excel的三种实现方式(二)
  15. 面对无秘,假设你是微信的产品经理浅析
  16. 2020数控机床数据采集
  17. 编辑Visio2016的自动对齐与粘附功能
  18. python在哪个城市工资高_“英语学科教学和笔译专业,哪个工资较高?”
  19. revit学习笔记-选项工具
  20. 医学3D建模有限元分析培训代做

热门文章

  1. 引入html5,html5-css的引入
  2. 李开复致中国大学生父母的一封信
  3. MT【193】三面角的正余弦定理
  4. 苹果平板做ppt方便吗_苹果手机和平板有什么软件可以做笔记
  5. TP-Link wr886n 路由器插上光纤后网速变慢问题
  6. 【mysql or条件是否走索引】
  7. Ubuntu 安装MTP驱动访问安卓设备
  8. Nico靠接外包,6个月当了老板,这操作绝了...
  9. 20176408李俊 栈和队列
  10. 关于Jquery导出word文档