C++函数重载中形参的const属性,《C++ Primer》

《C++ Primer》(第五版)P208

一个拥有顶层const(const修饰变量自身)的形参无法和另一个没有顶层const的形参区分开来:

Record lookup(Phone);
Record lookup(const Phone);    //编译错,重复声明了Record lookup(Phone)

变量或常量的实参都可以值拷贝给变量或常量的形参,因此无法判断调用上面哪个函数,C++干脆禁止形参列表只分是否是顶层const的重载。顶层const的指针也是如此:

Record lookup(Phone*);
Record lookup(Phone* const);    //顶层const指针,重复声明了Record lookup(Phone*)

上述两组函数声明中,每一组的第二个声明和第一个声明是等价的。验证:

void overrideFc2(int){ //与下面函数共同存在时编译报错重overrideFc2定义
    //值拷贝,实参可以是左值变量或左值常量,或右值
    std::cout<<"calling overrideFc(int)\n";
}
// void overrideFc2(const int){ //与上面函数共同存在时编译报错重overrideFc2定义
//     //值拷贝,实参可以是左值变量或左值常量,或右值
//     std::cout<<"calling overrideFc(const int)\n";
// }
void func8(){
    int num(9);
    const int cnum(10);
    overrideFc2(num);   //overrideFc2(int)与overrideFc2(const int)定义了哪个就调用哪个
    overrideFc2(cnum);  //overrideFc2(int)与overrideFc2(const int)定义了哪个就调用哪个
    overrideFc2(10);    //overrideFc2(int)与overrideFc2(const int)定义了哪个就调用哪个
}

    另一方面,如果形参是某种类型的指针或引用,则通过区分其指向的是常量对象还是非常量对象可以实现函数重载,此时的const是底层的

void overrideFc(int &){ //引用绑定,实参必须是左值变量
    std::cout<<"calling overrideFc(int &)\n";
}
void overrideFc(const int &){   //引用绑定,实参可以是左值常量或左值变量,或右值
    std::cout<<"calling overrideFc(const int &)\n";
}
void overrideFc(int *){ //值拷贝,实参必须是指向变量的指针左值,或变量的地址(右值)
    std::cout<<"calling overrideFc(int *)\n";
}
void overrideFc(const int *){   //值拷贝,实参可以是指向变量的指针或指向常量的指针,或常量的地址(右值)
    std::cout<<"calling overrideFc(const int *)\n";
}
void func7(){
    int num(7);
    overrideFc(num);    //如果只有overrideFc(const int &)则调用之,否则优先调用overrideFc(int&)
    const int cnum(8);
    overrideFc(cnum);   //只能调用overrideFc(const int &)
    overrideFc(9);      //calling overrideFc(const int &)
    int *pnum(&num);
    overrideFc(pnum);   //如果只有overrideFc(const int *)则调用之,否则优先调用overrideFc(int*)
    overrideFc(&num);   //变量的地址(右值),如果只有overrideFc(const int *)则调用值,否则优先调用overrideFc(int*)
    int const *cpnum(&num); //底层const
    overrideFc(cpnum);  //只能调用overrideFc(const int *)
    overrideFc(&cnum);   //常量的地址(右值),只能调用overrideFc(const int *)

}

变量实参可以传引用给变量引用,也可以传引用给常量引用,而常量实参只能传引用给常量引用。虽然也具有“歧义”,但相比实参变量或常量都可以值拷贝给形参变量或常量,歧义要少。

因而对变量实参,当只定义有常量引用的形参版本时则调用之,否则优先调用变量引用的形参版本。指向变量的指针也是一样,当只定义有指向常量的形参版本时就调用之,否则优先调用指向变量的形参版本

    特别地,常量引用const int &可以绑定到左值常量或左值变量,或右值。(因为常量引用表明了不会修改所绑定的对象,那么绑定一个右值也不是不行)。但指向常量的指针const int *,可以被变量的地址(右值)进行值拷贝,也可以被常量的地址(右值)进行值拷贝,对变量的地址值(右值),如果只定义有指向常量的指针的形参版本则调用之,否则优先调用指向变量的指针的形参版本。而常量的地址(右值),只能调用指向常量的指针的形参版本

    《C++ Primer》中更精炼的解释:因为const不能转换成其他类型,所以我们只能把const对象(或指向const的指针)传递给const形参。相反的,因为非常量可以转换成const,所以上面的4个函数都能作用域非常量对象或者指向非常量对象的指针。不过,当我们传递一个非常量对象或者指向非常量对象的指针时,编译器会优先选用非常量版本的函数

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值