C++重载函数分析

    C++重载函数的定义:同一作用域的多个函数,如果具有相同函数名而同时具有不同的形参列表,它们可以称为重载函数。

1 重载函数黑体关键词解析

1.1 相同函数名

        1)重载函数也是函数,所以需要函数名;函数名只是为了帮助编译器判断调用的是哪个函数而已。

        2)相同函数名正是重载函数引入的目的,对于一系列类似的操作省去为函数起名和记住函数名的麻烦,简化了程序实现,且使程序更容易理解。

1.2 同一作用域

    重载函数必须在同一作用域的原因是:C++有局部声明屏蔽全局声明的特性。这样如果在局部作用域有一个与外层作用域的重载函数同名的函数,该函数将屏蔽那些外层的重载函数。

例子如下:

void func(const string &);
void func(const double); //重载func

void f(int ival){
void func(int); //局部声明
func(”hello“);//error:因为func(const string &)被屏蔽了
func(ival); //ok:局部的func(int)可见
func(1.5);//ok:尽管全局重载函数func(const double)被屏蔽,但是可调用局部func(int),调用时实参1.5隐式转化为int型
}
但是如果将局部声明拿到函数外,位于同一作用域后,重载函数ok。
void func(const string &);
void func(const double); //重载func
void func(int); //重载func

void f(int ival)
{
   func(”hello“);//ok:调用func(const string &)
   func(ival); //ok:调用func(int)
   func(1.5);//ok:调用func(const double)
}


1.3 不同形参列表

     代码经过编译后会生成符号(symbol)表,函数调用是通过符号表中函数符号名来实现的(注意:函数名不同于函数符号名)。 C++中的函数符号名由函数名形参列表共同决定(函数符号名与函数返回值没有任何关系),形参列表包括形参个数和形参类型

    重载函数正是利用C++函数符号名这种特性来实现的,这样相同函数名如果使用不同形参列表,会生成不同函数符号名不会出现重复定义的问题)。

   判断不同形参列表时注意事项(注意下面people是类):

(1)形参名仅是帮助文档,不会影响形参列表

void func(const people &a); //形参名a
void func(people &);

(2)typedef仅提供别名,不会创建新的类型

typedef people p //p是people的别名
void func(const people &);
void func(const p &);


(3)调用带默认实参函数时,编译器可以忽略默认实参(这意味着用户可以给定实参也可以不给定),默认实参不影响参数个数

void func(const people1 &, const people2 &);
void func(const people1 &, const people2 & = ”“); //没有改变参数个数

(4)const形参

     a)对于函数值传递形参场合,const与非const是等价的形参;

void func(people1,people2);
void func(const people1, const people2);

     b)对于函数引用传递形参场合,const与非const是不同的形参;

void func(people &);
void func(const people &); //新函数,是func的重载函数

const people a(1,2);
people b;

func(a);//调用func(const people &)
func(b);//调用func(people &)

     c)对于函数指针传递形参场合,指向const对象与指向非const对象是不同的形参;

        注意:基于指针本身是否为const不能实现函数重载

void func(int *);
void func(int * const); //属于重复声明


2 重载函数的函数匹配与实参类型转换

    匹配的结果有3种可能

   1)编译器找到最佳匹配函数,生成调用函数代码;

   2)编译器找不到匹配函数,编译出错;

   3)找到多个匹配函数,但是没有一个是最佳匹配函数,调用具有二义性;


2.1 重载函数匹配3个步骤

void func();
void func(int);
void func(int, int);
void func(double, double = 1.2);

func(1.35); //调用func(double, double = 1.2)

1)查找候选函数

    与被调用函数同名的函数都可以称为候选函数。上面例子中候选函数有4个。

2)确定可行函数

    可行函数需要满足2个条件:

    a)被调函数实参与函数形参个数相同;

    b)被调函数实参与函数参数类型匹配,或者可以通过隐式转化为类型匹配  ;

3)决定最佳匹配

    最佳匹配原则:

    a)实参与形参类型精确匹配优于需要类型转化后的匹配

    b)多参数最佳匹配特点

       i)每个实参匹配不劣于其它可行函数;

      ii)至少有一个实参优于其它可行函数;

     func(1,1.5)调用分析:

    第一步候选函数:4个

    第二步:可行函数func(int,int)和func(double,double)

    第三步:最佳匹配,只看实参数1精确匹配func(int,int),再看实参2精确匹配的是func(double,double),2个函数形参优劣相当这样找不出最佳匹配,出现了”二义性“。

    解决二义性办法是显式强制类型转换,但是强制类型转换不是最好的,要避免;出现这样情况表明形参设计不合理。

func(static_cast<double>(1), 1.5)//调用func(double,double)
func(1, static_cast<int>(1.5)) //调用func(int,int)

2.2 实参类型转换

实参类型转换分为4级:

1)精确匹配,实参与形参类型一致

2)通过类型提升实现匹配;

3)通过标准转换实现匹配;

4)通过类类型转换实现匹配;

注意:

a)类型提升实现匹配优于标准转换实现的匹配

extern void func(long);
extern void func(float);

func(3.14); //造成二义性,因为都是使用标准转换,没有说哪个更优

b)较小整型提升为int型

extern void func(int);
extern void func(short);

func('c'); //char提升为int,匹配到函数func(int)

c)枚举对象只能用同类型枚举对象或者枚举成员初始化

enum Test {T1 = 1, T2 = 130};
extern void func(Test);
extern void func(int);

void main()
{
  Test test = T1;
  func(10);//调用func(int)
  func(T1); //调用func(Test)
  func(test);//调用func(Test)

  return 0;
} 

d)枚举值可以传递给整型形参,整型值不能传递给枚举形参

enum Test {T1 = 1, T2 = 130};
extern void func(int);
<pre name="code" class="cpp">extern void func(unsigned char);

unsigned char uchar = 130;
func(T2); //调用
func(uchar);//调用

 

3 参考资料

   C++ primer


 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值