高效学 C++|函数参数的引用传递和函数重载
C++语言中函数的声明形式如下:
如声明将两个整型参数相加的函数 add()的程序如下:
下面从函数参数的引用传递、函数重载两个方面介绍 C++语言中的函数。
01、引用传递
引用是一种特殊的声明,可以用来限定变量的类型。如果在声明一个变量的同时将它声明为另一个变量的引用,则意味着这两个变量等同于一个变量,即声明为引用的变量是它所引用的变量的别名。下面的程序中将变量 ri 声明为变量 i 的引用。
使用引用时必须注意下面两个问题。
(1)定义一个引用时,必须同时对它初始化,即明确它所引用的变量。
(2)引用类型的变量所引用的那个变量只能在初始化时指定,指定之后不能修改(实际上也没法修改)。
实际上,编译器对引用类型的变量自动地按照指针常量的形式进行了变换,编译器变换上面声明引用变量 ri 的语句如下:
这样,就可以很清楚地看到 ri 是一个常变量,该常变量是一个指针常量,并且该指针指向一个 int 型数据。因为 ri 是常变量,所以声明时必须要初始化,也因此不能在声明之后修改它的值。这就很好地解释了为什么对引用类型的变量有前面两条的限制。
同理,编译器将前面给引用变量 ri 赋值的语句自动地改写为:
综上,编译器把“引用”改成了“指针”,所做的变换如下:
(1)将引用运算符“&”转换成指针运算符“* const”。
(2)在定义引用类型的变量时对右值取地址。
(3)对于函数的形参,如果它是引用类型,则形实结合时对实参取地址。
(4)对于使用引用变量的语句,在引用变量前加“*”。
总之,编译器自动地把“引用”改成了“指针常量”。
使用引用类型可使程序变得简洁、容易理解。使用引用类型的形参如例 1 所示。在该例中,swap 函数完成两个数据的交换:函数中是交换形参的值,但由于形参是引用类型,所以实际上完成了实参的交换。在本例中,交换前变量 x 等于 5,变量 y 等于 10;交换后变量 x 等于 10,变量 y 等于 5。
【例 1】 使用引用类型的形参。
例 2 说明了函数返回引用类型的情况,此时可直接给函数调用后的返回值赋新值:变量 x 和变量 y 的初值分别是 2 和 5;在调用了 larger()函数之后给其返回值加 5,由于变量 y 的初值较大且 larger()函数的形参和返回值都是引用类型,所以实现了将变量 y 的值增 5 的功能,因此程序最后一行的输出为“x = 2 y = 10”。
【例 2】 函数返回引用类型。
函数返回引用类型的数据是经常用到的,因为返回值经常需要作为左值。需要注意的是,不能将非静态局部变量按引用类型返回,因为在函数返回后,该局部变量已经不存在了,从而返回值也不能作为左值。比如例 3 中,将 larger()函数改为如下形式时将会出现警告。
两种使用引用传递的主要情形如下:
(1)用于传递大量数据。因为引用传递被自动转换为指针传递,这能够减少复制数据的开销。
(2)用于返回一个内存空间作为左值。比如上面的 larger()函数,为了能够给其返回值赋值,需要使用引用(或采用相应的指针形式,但比较麻烦)。
02、函数重载
在面向对象程序设计中,成员函数是对类的行为的描述。对于同一个类,存在这样一种情况:虽然它执行的动作的称谓是相同的,但在不同的情况下执行的过程却是不同的。对于普通的函数也是如此。比如,已知两个数,要求把它们加起来。此时,如果这两个数是整数,那么可以用整数的加法运算完成计算;如果已知的数是虚数,那么可以用虚数的加法运算来完成计算。对于这样的“把两个数相加”的要求,可以把它们抽象成函数。不过,由于执行过程不同,在 C 语言中需要使用不同的函数名来完成,如下面的函数声明所示(假设 complex 是已定义好的表示虚数的类型)。
显然,这样设计不利于阅读和使用。为解决此类问题,在 C++语言中引入了函数重载的概念,即允许声明同名的函数。对于一个函数调用,编译器根据实参和形参的类型、个数及顺序自动确定调用哪个同名函数。比如上面两个函数可重新声明如下:
在调用函数时,根据实参的类型来选择调用哪个函数:如果实参是整型,则调用第一个函数版本;如果实参的类型是虚数,则调用第二个函数版本。
实际上,编译器在编译 C++语言的源程序时自动重命名了重载函数,重命名的方式大致是函数名加上参数类型列表,如上面两个函数会被重命名为类似于下面的形式。
而对于调用语句“add(1, 2);”则会自动变为“add_int_int(1, 2);”。通过这种方式,编译器能够确定需要调用函数的哪个重载形式。
从上面的程序也可看出,在使用函数重载时要注意:尽管函数名可以相同,但形参的类型、个数及顺序一定要有不同,否则编译器就无法确定到底该调用哪个函数了。另外,函数的返回值类型不能用来区分函数的重载形式,因为在调用函数时常常不关心返回值,从而编译器也无法利用返回值的类型来确定该调用哪个函数。示例程序如下:
版权声明: 本文为 InfoQ 作者【TiAmo】的原创文章。
原文链接:【http://xie.infoq.cn/article/833c15e4488aecee59724b6c9】。文章转载请联系作者。
评论