重载函数

  • const is irrelevent for nonreference parameters
    对于非引用传参,复制形参时并不考虑形参是否为 const——函数操纵的只是副本,但在在函数里面,const和非const的形参是有区别的
    有 const 引用形参的函数与有非 const 引用形参的函数是不同的。
    1 Record lookup(Phone);
    2 Record lookup(const Phone); // redeclaration
    3 //此为重复声明,而非重载
    1 void write(const int &a)
    2 {
    3     value = a;
    4 }
    5 void write(int &a)
    6 {
    7     value = a;
    8 }
    9 //重载
  • 在一些情况下,使用不同的函数名能提供较多的信息,使程序易于理解,就不必要用重载
  • 如果局部地声明一个函数,则该函数将屏蔽而不是重载在外层作用域中声明的同名函数 ,由此推论,每一个版本的重载函数都应在同一个作用域中声明
     1 #include <iostream>
     2 using namespace std;
     3 void func()
     4 {
     5     cout << "out" <<endl;
     6 }
     7 void print(double a){cout << a <<endl;;} // overloads the print function
     8 void fooBar(int ival)
     9 {
    10     void print(int);// new scope: hides previous instances of print
    11     print(ival); // ok: print(int) is visible
    12     print(3.14); // ok: calls print(int); print(double) is hidden
    13 }
    14 void print(int)
    15 {
    16     cout << "3" <<endl;
    17 }
    18 int main()
    19 {
    20     fooBar(22);
    21     return 0;
    22 }

    执行的两个print都是print(int),print(double)被屏蔽


    调用 print 时,编译器首先检索这个名字的声明,找到只有一个 int 型形参的print 函数的局部声明。一旦找到这个名字,编译器将不再继续检查这个名字是
    否在外层作用域中存在, 即编译器将认同找到的这个声明即是程序需要调用的函数,余下的工作只是检查该名字的使用是否有效。

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

    1 void print(const string &);
    2 void print(double); // overloads print function
    3 void print(int); // another overloaded instance
    4 void fooBar2(int ival)
    5 {
    6 print("Value: "); // ok: calls print(const string &)
    7 print(ival); // ok: print(int)
    8 print(3.14); // ok: calls print (double)
    9 }

    先找到所有print函数,再逐个匹配参数类型

  • 有多个符合要求的重载函数时按照参数最佳匹配的原则调用重载函数:实参类型与形参类型之间的精确类型匹配比需要转换的匹配好
    如果在检查了所有实参后,仍找不到唯一最佳匹配函数,则该调用错误。编译器将提示该调用具有二义性
     1 #include <iostream>
     2 using namespace std;
     3 int reset(int a, int b, int c)
     4 {
     5     cout << "1" <<endl;
     6     return a;
     7 }
     8 double reset(double a, double b, double c)
     9 {
    10     cout << "2" <<endl;
    11     return a;
    12 }
    13 int main()
    14 {
    15     reset(1.0, 3, 2);
    16     return 0;
    17 }

    此时,实参一个为int,一个为double,无论使用哪一个重载函数,都需要转换,所以没有唯一的最佳匹配函数,会报错

    虽然实参里有2个int,而只有一个double,但是只要有类型转换,就都是同级别的
    解决这样的二义性,可通过显式的强制类型转换强制函数匹配 : reset(1.3, static_cast<double>(3), static_cast<double>(2));
  • 什么是候选函数?什么是可行函数?
    1.候选函数是指在调用点上其声明是可见的且与被调用的函数同名的函数。
    2.可行函数是指从候选函数中选出的函数,必须满足下列条件:函数的形参数目与该函数调用的实参数目相同;
    每个实参的类型必须与对应形参的类型匹配,或者可以隐式转换为对应形参的类型。

    即:候选函数是所有与被调函数同名且可用的函数,可行函数是参数符合要求的函数

  • 必须注意的一个重点是较小的整型提升为 int 型。假设有两个函数,一个的形参为 int 型,另一个的形参则是 short 型,对于任意整型的实参值,int 型版本都是优于 short 型版本的较佳匹配
  • 需要类型转换的匹配“劣于”需要类型提升的匹配
  • 整数对象即使具有与枚举元素相同的值也不能用于调用期望获得枚举类型实参的函数
     1 enum Tokens {INLINE = 128, VIRTUAL = 129};
     2 void ff(Tokens);
     3 void ff(int);
     4 int main() {
     5 Tokens curTok = INLINE;
     6 ff(128); // exactly matches ff(int)
     7 ff(INLINE); // exactly matches ff(Tokens)
     8 ff(curTok); // exactly matches ff(Tokens)
     9 return 0;
    10 }
  • 虽然无法将整型值传递给枚举类型的形参,但可以将枚举值传递给整型形参。此时,枚举值被提升为 int 型或更大的整型。具体的提升类型取决于枚举成员的
    值。如果是重载函数,枚举值提升后的类型将决定调用哪个函数:
    enum Tokens {INLINE = 128, VIRTUAL = 129}; 
    1 void newf(unsigned char);
    2 void newf(int);
    3 unsigned char uc = 129;
    4 newf(VIRTUAL); // calls newf(int)
    5 newf(uc); // calls newf(unsigned char)
  • const和非const指针作为形参时重载规则同引用
  • 1 注意不能基于指针本身是否为 const 来实现函数的重载:
    2 f(int *);
    3 f(int *const); // redeclaratio
    const 用于修改指针本身,而不是修饰指针所指向的类型

     

posted @ 2020-06-24 12:25  幻想Elapse  阅读(286)  评论(0编辑  收藏  举报