C++中的引用类型属于复合类型(compound type)。复合类型指的是基于其它类型定义的类型。
引用(reference)为对象起了另外一个名字,引用类型引用(refers to)另外一种类型。通过在变量名前添加“&”符号来定义。
引用必须用与该引用同类型的对象初始化。
定义了一个引用之后,对其进行的所有操作都是在与绑定的对象上进行的。
此时,ival 的值变为 7 。如果同一作用域的几个函数名字相同但形参列表不同,那么这些函数称为重载(overloaded)函数。如
以上三个函数的函数名相同,但是形参列表不同。因此,这三个print() 函数是重载函数。
函数匹配(funtion matching)是指一个过程,在这个过程中我们把函数调用与一组重载函数中的某一个关联起来。编译器首先将调用的实参与重载集合中每一个函数的形参进行比较,然后根据比较的结果决定到底调用哪个函数。例如
print(“hello world”);
编译器将调用print()函数的实参”hello world”与三个print()函数中的形参表进行比较,最终决定此时应该调用
void print(const char *cp);
函数。
在进行编译器进行函数匹配时,可能会遇到如下三种情况。
(1)编译器找到一个与实参最佳匹配的函数,并生成调用该函数的代码。
(2)找不到任何一个函数与调用的实参匹配,此时编译器发出无匹配的错误信息。
(3)有多于一个函数可以匹配,但是每一个都不是明显的最佳选择,此时也会发生错误,称为二义性调用。
在“2.1重载函数定义”中提到,重载函数的主要区别在于形参表的不同。在函数的形参表中,可以通过引用类型和非引用类型进行区分。
有如下两个函数
在“1 引用”中提到,引用属于复合类型,因此 int 和 int 的引用属于两种不同的类型,即这两个 func() 函数的形参列表不同,所以这两个函数是重载函数。使用以下代码来调用void func(int param);函数
此时,编译器的错误提示信息为错误,有多个重载函数“func”实例与参数列表匹配
函数“func(int)”
函数“func(int&)”
参数类型为(int)
在“1.2 引用使用”中提到,对引用对象的操作是在与其绑定的对象上进行的。因为,引用是其绑定对象的另一个名字,以下两种调用方式中
编译器无法区别实参value 或者 refvalue 到底是 int 类型还是 int 类型的引用。这就是在“ 2.2.2 调用重载函数可能遇到的情况”中提到的二义性调用。(1)调用func(int)函数
如果想调用func(int)函数,可以将其实参设置为整数常量,例如
const int value = 1;
func(value);
或者
func(1);
(2)调用func(int&)函数
如果想调用func(int&)函数,则需要通过显示转换操作符static_cast将函数进行转换
static_cast<void(*)(int&)>(func)(refvalue);
相关链接:static_cast强制类型转换符号的格式为
static_cast<type>(expression)
其中,type为要强制转换后的类型,而expression是要被强制转换的表达式。例如
以上代码的的功能是将void* 类型的变量 p 强制转换为 double* 类型。所以
代码的功能就是将函数调用代码func(refvalue) 强制转换为 void(*)(int&) 格式,即调用了 func(int&) 。
使用static_cast强制转换符也可以调用func(int)
有如下两个函数
那么这两个func() 函数是重载函数。采用以下代码调用这两个重载函数
其中,func(refvalue); 调用的是func(int&) 函数;而func(refvalue_const); 调用的是func(const int&) 函数。在“3.2 常量引用与非常量引用参数”中提到的常量引用和非常量引用指的是引用所代表的变量是常量还是变量;而本节提到到引用常量和引用非常量值得是引用本身是常量还是变量。
以上两个函数的形参即为引用非常量和引用常量。需要注意的是,形参列表不能通过引用常量和引用非常量进行区分,即以上两个函数是同一个函数的声明。此时,编译器会报如下错误error C2084: 函数“void func(int &)”已有主体