Cpp Primer<<学习函数-重载函数_2

<<重载函数>>
在同一作用域中,具有相同名字而形参表不同的两个函数数,成为重载函数。
函数重载简化了程序的事项,使程序更容易理解。函数名只是为了帮助编译器判断调用的是哪个函数而已。

Record lookup(const Account&);  //find by Account
Record lookup(const Phone&);  //find by Phone
Record lookup(const Name&);  //find by Name
Record r1,r2;
r1 = lookup(acct);     //call version that takes an Account
r2 = lookup(phone);    //call version that takes a phone

编译器根据实参的类型来判断调用的是哪个函数。
任何程序都仅有一个main函数的实例。main函数不能重载。
<函数重载和重复声明的区别>
两个函数声明的返回类型和形参表完全匹配,则将第二个函数声明视为第一个的重复声明。若返回值类型不同,函数其他部分相同,则第二个声明是错误的:

Record lookup(const Account&);
bool lookup(const Account&);//error:only return type is defferent

函数不能仅仅基于不同的返回类型而实现重载。

Record lookup(Phone);
Record lookup(const Phone&);  //Redeclaration
形参与const形参的等价性仅适用于非引用形参。函数形参表带有const引用和非const引用或者指向const类型的指针形参和指向相同类型的非const对象的指针形参的函数不相同。

<重载与作用域>
局部声明的名字将屏蔽在全局作用与内声明的同名名字。

string init();  // the name init has global scope
void fcn()
{
    int init = 0; // init is local and hides global init
    string s = init(); // error:global init is hidden
}

一般的作用域规则同样适用于重载函数名。局部地声明一个函数,将屏蔽在外层作用域中声明的所有同名函数。
函数的声明应放在头文件中。

void print(const string &);
void print(double); //overloads the print function
void fooBar(int ival)
{
    void print(int); // new scope:hides previous instances of 
                     // print
    print("Value:"); // error:print(const string &) is hidden
    print(ival); // ok:print(int) is ivisible,calls print(int);
    print(3.14); // ok:calls print(int); print(int) is 
                 // hidden,calls print(int);
}

调用print时,编译器首先检索这名字的声明,找到一个int型形参的print函数的局部声明。一旦找到,编译器将认定该函数即是程序需要调用的函数,余下工作只是检查该名字的使用是否有效。在C++中,名字检查发生在类型检查之前。
在与其他print函数相同的作用域中声明print(int),则该函数就成为一个重载函数了。

void print(const string &);
void print(int);
void printf(double);
void fooBar(int ival)
{
    print("Value:"); //ok: calls print(const string &)
    print(ival);      //ok: calls print(int)
    printf(3.14);     //ok: calls print(double);
}

<函数匹配与实参转换>
函数重载确定(函数匹配)是将函数调用与重载函数集合中的一个函数相关连的过程。
通过自动提取函数调用中的实参与重载函数集合中各个函数提供的形参做比较来实现调用与函数的匹配。
匹配有三:

  1. 编译器找到与实参最佳匹配的函数,并生成调用该函数的代码。

  2. 找不到形参与函数调用的实参匹配的函数,这种情况下,编译器将给出编译错误信息。

  3. 存在多个与实参匹配的函数,但没有一个是明显的最佳选择,这种情况也是错误的,该调用具有二义性。

<重载确定的三步骤>

  1. 候选函数。候选函数是与被调用函数同名的函数,并在调用点上,它的声明是可见。

  2. 选择可行函数。

    • 可行函数必须满足条件:
      ①函数形参个数与该调用的实参个数相同;
      ②各个实参类型与对应形参的类型匹配,或者可被隐式转换而对应的形参类型。

若函数具有默认实参,则调用函数时,实际传递的实参可能比实际需要的少。默认实参也是实参,在函数匹配过程中,它的处理方式与其他实参一样。找不到可行函数,则在该函数调用点上,该调用则是错误的,最终导致编译则无法通过。

void fun(int,int);
void fun(double,double =2.0)
int main()
{
    fun(5.6);  //ok:calls fun(double,double = 2.0)
    fun(45); // ok:calls fun(double,double = 2.0),but warning
    return 0;
}

3.寻找最佳匹配(如果有的话)

在找到可行函数的前提下,所用的实参类型与函数的形参类型能够精确匹配,或者是实参类型能够隐士转换为形参类型。

4.含有多个形参的重载确定

编译器通过一次检查各个实参来决定哪个或哪些函数匹配最佳。若有且仅有一个函数满足下列条件,则匹配成功:
①其每个实参的匹配都不劣与其他可行函数需要的匹配。
②至少有一个实参的匹配优于其他可行函数提供的匹配。

void fun(int,int);
void fun(double,double);
int main()
{
    fun(42,2.56); // error:call ambigously
    fun(static<int>(42),2.56); // ok:call fun(double,double);
    fun(42,static<int>(2.56)); // ok:calls fun(int,int)
    return 0;
}

这样子将出现函数调用的二义性。调用出现二义性。编译器也不知道在调用点处生成调用哪个函数的代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值