用const进行函数重载的行为

时间:2014-10-26 12:44:11

标签: c++ overloading

我正在研究g ++,在这里我试图通过向参数添加const来重载函数。它工作正常,当它运行时,它调用没有const

的函数
  1. 此行为是否在C ++标准中指定?
  2. 在没有const

    的情况下调用该函数的原因是什么
    void print(const std::string& str){std::cout << "const" << str << std::endl;}
    
    void print(std::string& str){std::cout << str << std::endl;}
    
    int main()
    {
       std::string temp = "hello";
       print(temp);
       return 0;
    }
    

6 个答案:

答案 0 :(得分:2)

引用绑定是一个标识类别§13.3.3.1.4)但由于后者更符合cv,对于§13.3.3.2,非const是首选(来自的示例代码)标):

int f(const int &);
int f(int &);

int i;
int j = f(i); // calls f(int &)

答案 1 :(得分:1)

这是标准行为。任何其他行为都会导致疯狂行为。特别是,非const函数根本不可调用。

答案 2 :(得分:1)

const是方法签名的一部分。覆盖仅适用于具有相同签名的方法。 当您使用基类的const方法调用子类的const方法时,这种行为是为了避免相反的情况。

答案 3 :(得分:1)

原因是[over.ics.rank] / 3中的这一部分明确涵盖了这一部分:

  

标准转换序列S1是一个比转换序列更好的转换序列   标准转换序列S2如果[...] - S1S2是参考   绑定(8.5.3),以及引用引用的类型   相同的类型,除了顶级cv限定符,以及其类型   由S2引用初始化的引用比cv更合格   由S1初始化的引用引用的类型。

S1对应第二个重载,S2对应第一个重载。

  

没有const

的情况下调用该函数的原因是什么

您总是尝试选择最专业的东西。就像在函数模板的部分排序中那样,在重载解析中就是这种情况。第二个重载比第一个重载更专业,因为第一个重载可以使用参数调用,第二个不能被调用 - 这是此规则背后的基本推理。

答案 4 :(得分:1)

通过匹配参数的类型(包括限定符)来重载。在您的情况下,temp的类型std::string不是const std::string。你只用一个文字常量初始化它,它本身不是常数。

请考虑以下事项:

std::string temp( "hello" ) ;
print(temp);                                    // hello   
print( std::string("hello") ) ;                 // consthello
print( "hello" ) ;                              // consthello
print( static_cast<const std::string>(temp) ) ; // consthello

const std::string temp2( "hello" ) ;
print(temp2);                                    // consthello   

如果要删除非const版本,则所有三个都将调用剩余的const重载。在此示例中,实际上只有const版本是必需的(并且是首选的),因为两个版本都不修改字符串对象。

如果另一方面你删除了非const版本,除了上面的第一个例子之外,没有任何功能匹配,并且构建将失败。也就是说非const对象可以安全地作为const参数传递,但是const对象不能作为非const参数传递,因为该函数不是&#34;有希望&#34;不要修改对象。您可以通过const_cast将const强制转换为非const参数,如下所示:

const std::string temp2("hello") ;
print( const_cast<std::string&>(temp2) ) ;    // hello

但是如果在这种情况下print()试图修改对象,结果是 undefined ,那么请认为这种做法不安全。

使参数const表示意图,允许编译器在代码尝试修改对象或通过非const参数将其传递给其他函数时发出诊断。它还可能为编译器提供优化可能性。

答案 5 :(得分:0)

因为调用std::string const&的函数需要两次隐式转换:一次转换为std::string const,一次转换为std::string const&;调用函数std::string&只需要一次隐式转换(到std::string&),因此首选。{/ p>