关于函数的调用和函数的匹配规则浅析

本文探讨了C++中函数调用的匹配原则,包括如何确定最佳匹配函数,以及函数匹配的顺序,涉及完全匹配、提升转换和标准转换等概念。还通过实例分析了函数匹配的具体应用。

//这里我不包含关于模板的详细匹配规则.

 

首先明白两个概念:

函数匹配:调用函数时,究竟调用哪一个重载函数。

二义性:错误情况,是指在调用重载函数时编译器不知道应该调用哪一个重载函数(有多个可选函数)。

函数的匹配过程如下:

1.确定候选函数:与被调函数同名的函数,并且在调用出这些函数在调用点是可见的。
2.选择可行函数:从候选函数中选择一个或者多个函数,这些函数都是可以被调用函数正确调用的。
    
    关于可行函数的选择的规则如下:
        1.形参数目应该等于或者大于(存在默认参数)实参个数。
            void fun(int a, int b ,int c=20);
            fun(10, 20);
            fun(10, 20, 30);    
        
        2.实参可以通过隐式转换与对应的形参类型进行匹配。
          
            void fun(int a);
            char c = 'c'; 
            fun(c);
3.确定最佳匹配项的可行函数:若有就调用她,否则出错。

下来我将一点一点的记录我所知的注意点。

首先在确定候选函数的时候:

我们应该注意,在局部域中的声明的函数会屏蔽外层作用域中的同名函数。



#include<iostream>

void test() {
	std::cout << "啦啦啦" << std::endl;
}


void test(int differ) {
	std::cout << "巴扎黑!" << std::endl;
}

namespace gdl {
	void test(int *ptr) {}

	void fun() {
		//test(20);//error!!! 中不到匹配的函数.
	}
}

====确定最佳匹配函数的方法====

 

1.首先明确一点:最佳匹配函数并不一定是完全匹配或者完美匹配的,只是说是可行函数中最佳匹配调用实参的。

最佳匹配的匹配次序(最佳到最差)依次为完全匹配 - 通过提升转换实现的匹配 - 通过标准转换实现的匹配 - 通过类型转换实现的匹配

标准转换

1.整形标准转换:如long->int, int -> short, ....

2.浮点型标准转换:double->float

3.整形与浮点型的相互转换

4.指针转换:任意指针到void*的转换,

5.bool转换:任意类型到bool型的转换

//标准转换,大概也就是说的标准类型之间的转换。不包含提升转换。
//然后值得注意的是:任何指针类型转换成void*的优先级高于装换为bool类型。
//且同为标准转换时没有谁优先于谁之说(exclude 上面一条。!!!)。

提升转换

1.float到double的转换

2.char到int的转换, short到int的转换...boo->int

//提升转换也就是再同类型如同为整形,同为浮点型的情况下,类型提升的转换。

-------------

转换序列

转换序列:实参到形参的转换往往需要经过多次转换,谓之转换序列。
转换序列一般由以下顺序构成:
    1. 0次或一次的左值转换(包括左值到右值的转换,数组到指针的转换,函数到指针的转换)
    2. 0次或者一次的(提升转换|标准转换),一般提升转换和标准转换不同时存在。
    3. 0次或者1次的限定修饰转换

转换序列的等级:构成转换序列的最坏的等级。

void fun(int a);
float x = 10.0;
fun(x);

//在上面的转换中:
1.左值转换:提取x的值创建临时变量
2.标准转换:临时变量从float向int进行标准转换。

所以此次匹配中转换序列的等级为:标准转换

完全匹配:完全匹配形参和实参并不完全一致,完全匹配允许一些无关紧要的转换存在。

完全匹配所允许的无关紧要的转换如下:

1. 左值到右值的转换

2. 数组到指针的转换

3. 函数到指针的转换

4. 限定修饰转换,即const和非const, volatile和非volatile的转换

注意:底层const的const不能再转换中去掉const:
    实参转换到形参:
        const type* -> type*;        //Error.
        const type& -> type&;        //Error.

左值到右值的转换:表示从左值表示的对象中抽取值得过程。

思考一下:左值到右值的转换存在的原因是否是:运算不能直接在内存之间发生?

然后简单地谈一谈const和volatile对最佳匹配等级的影响:

    当同为完全匹配时,形参带const的优先级低于不带const的优先级

    --------------------
    void fun(int * pa);
    void fun(const int * pa);
    int a = 10;
    fun(&a);
    虽然连个重载函数同为完全匹配,但是由于const的存在导致fun(&a)的调用匹配的是void fun(int*);
    //看起来也是挺合理的.

==============

1. 同为完全匹配,普通函数优先于模板函数或者特化的模板函数。
2. 当完全匹配函数只有模板函数时,模板函数的优先级更高
3. 看起来也很合理.

==========实例分析:

=============
1. void f(int a){}
2. void f(float a, float b= 3){}
3. void f(char a){}
4. void f(const char * a){}
5. void f(const char &a){}

//call.
char c= 'c';
f(c);

转换序列分析:
1. 左值转换 -> 提升转换
2. 左值转换 -> 标准转换
3. 完全匹配
4. 不能匹配,不在候选函数之列
5. 完全匹配,且const无影响

所以,此调用在3,5重载上存在二义性。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值