C++ 7.8.1 重载函数

简介

- 出现在相同作用域中的两个函数,如果具有相同的名字而形参不同,则称为 重载函数。(前提是在相同的作用域内!!!!)
- 任何程序都仅有一个main函数,main函数不能重载
- 一般的作用域规则同样适用于重载函数名。如果局部地声明一个函数,则该函数将屏蔽而不是重载在外层作用域中声明的同名函数。
- 每一个版本的重载函数都应该在同一个作用域中声明。

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

一、重载函数

1、重载函数简介

  • 出现在相同作用域中的两个函数,如果具有相同的名字而形参不同,则称为重载函数。(前提是在相同的作用域内!!!!)

  • 任何程序都仅有一个main函数,main函数不能重载

  • 要理解函数重载,必须理解如何定义一组重载函数和编译器如何决定对某一调用使用哪个函数。

Record lookup(const Account &);
Record lookup(const Phone &);
Record lookup(const Name &);
Record r1,r2;
r1=lookup(acct);
r1=lookup(phone);

//这里的三个函数共享同一个函数名,但却是三个不同的函数。编译器根据所传递的实参类型来判断调用的是哪个函数。

2、函数重载和重复声明的区别

  • 如果两个函数声明的返回类型和形参表(形参类型及个数)完全匹配,则将第二个函数声明视为第一个的重复声明。

  • 如果两个函数的形参表完全相同,但返回类型不同,则第二个声明是错误的

  • 函数不能仅仅基于不同的返回类型而实现重载(你还要看形参表),有些看起来不相同的形参表本质上是相同的。

  • 所以看是不是重载,首先看形参表是否完全匹配,如果不匹配则是重载,不能看返回类型

Record lookup(const Account&);
bool lookup(const Account&);//错误!!!!!不是重复声明,这个函数声明是错误的!!

int *reset(int *);
double *reset(double *);//声明了一个函数的重载
重要的例子!!!
Record lookup(const Account& acct);//给形参命名了,但形参只是帮助文档,并没有修改形参表
Record lookup(const Account& );//忽略形参的名字 ,这两个是一个函数声明

typedef Phone Telno;// Telno是Phone的同义词,两者是同一个类型
Record lookup(const Phone&);
Record lookup(const Telno&); //Telno和Phone是相同的类型,所以这个和上面那个声明一样

Record lookup(const Phone&,const Name&);
Record lookup(const Phone&,const Name& =" ");
//上面这两个函数,形参列表只有默认的实参不同,默认实参并没有改变形参的个数。无论实参是由用户还是编译器提供,这个函数都带有两个实参,是同一个函数的声明

Record lookup(Phone);
Record lookup(const Phone);//两个是相同的声明
//这两个函数的区别在于是否将形参定义为const,这种差异并不影响传递至函数的对象,
//第二个函数声明被视为第一个的重复声明。其原因在于实参传递的方式。复制形参时并不考虑形参是否为const---函数操纵的只是副本。函数无法修改实参。结果,既可以将const对象传递给const形参,也可传递给非const形参,这两种形参并无本质区别。

Record lookup(Phone&);
Record lookup(const Phone&);//这两个是不同的声明!!!!
//值得注意的是,形参与const形参的等价性仅适用于非引用形参。有const引用形参的函数与非const引用形参的函数是不同的(7.2.2)。

//类似的,如果函数带有指向const类型的指针形参,则与带有指向相同类型的非const对象的指针形参的函数不同、
Record lookup(Phone*);
Record lookup(const Phone*);//这两个是不同的声明!!!!(4.2节)

3、建议:何时不重载函数名

二、重载与作用域

  • 在2.3.6节程序演示了C++作用域的嵌套,在函数中局部声明的名字会屏蔽在全局作用域内声明的同名名字。这个关于变量名字的性质对于函数名同样成立。
string init();//这个init具有全局的作用域
void fcn(){
    int init =0;//局部变量init ,覆盖了全局的那个init
    string s=init();//错误!!!全局init被覆盖了
}
  • 一般的作用域规则同样适用于重载函数名。如果局部地声明一个函数,则该函数将屏蔽而不是重载在外层作用域中声明的同名函数。

  • 每一个版本的重载函数都应该在同一个作用域中声明。

  • 局部地声明函数是一种不明智的选择,函数的声明应该放在头文件中。

  • 在C++中,名字查找发生在类型检查之前。

void print(const string &);
void print(double);     //重载print函数
void fooBar(int ival){ 
   void print(int);     
   //新的函数声明,屏蔽了print的其他声明,在这个作用域或嵌套在这个作用域里的其他作用域中,名字print的任何作用都将解释为这个print函数实例。
   print("Value: ");    //错误!!!!!只找到void print(int)这个函数
   print(ival);         //正确    只找到void print(int)这个函数
   print(3.14);          //正确   只找到void print(int)这个函数

//调用print时,编译器首先检索这个名字的声明,找到只有一个int型形参的print函数的局部声明。一旦找到这个名字,编译器将不再继续检查这个名字是否在外层作用域中存在,即编译器将认同找到的这个声明即使程序需要调用的函数,余下的工作只是检查该名字的使用是否有效。
//第一个函数调用传递了一个字符串字面值,但是函数的形参却是int型的。字符串字面值无法隐式地转换为int型,因此该调用是错误。print(const string &)函数与这个函数调用匹配,但已被屏蔽,因此不在解释该调用时考虑。
//当传递一个double数据调用print函数时,编译器重复了同样的匹配过程:首先检索到print(int)的局部声明,然后将double型的实参隐式转换为int型。因此,调用合法、
}
void print(const string &);
void print(double);     //重载print函数
void print(int);        //重载print函数
void fooBar(int ival){ 
   套在这个作用域里的其他作用域中,名字print的任何作用都将解释为这个print函数实例。
   print("Value: ");    //正确  调用void print(const string &)这个函数
   print(ival);         //正确  这个函数调用void print(int)这个函数
   print(3.14);         //正确  调用void print(double)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值