不正确的重载决策,const参数值为0

时间:2016-06-09 11:35:57

标签: c++ const overloading c++98

我有一个班级B,其中包含两个重载函数int Set(B *);int Set(const A&);。类A需要构造函数参数unsigned char。使用值为Set的{​​{1}}调用const unsigned char时,会将其解析为0,而当传递的值为非零时,它会解析为{{1} (按照我的期望)。

重载决策适用于非const Set(B*),但失败时Set(const A&)的值设置为unsigned char。为什么呢?

以下代码说明了使用const和非const const unsigned char

调用0时的差异
Set

输出(由unsigned char c ++ 98编译): Demo - 关于ideone c ++ 5.1

#include <iostream>

using namespace std;


class A{
  char m_byteValue;
public:
  A(unsigned char c) {
    m_byteValue = c;
  }
};


class B{
  int m_a;
public:
  B(){
    m_a = 2;
  }
  int Set(B *);
  int Set(const A&);
};

int B::Set(const A& v) {
  cout << "I am in the const ref function\n";
  return 0;
}

int B::Set(B* p) {
  cout << "I am in the pointer function\n";
  return 0;
}

int main(){
  const unsigned char a = 0;
  const unsigned char b = 1;
  unsigned char c = 0;
  unsigned char d = 1;
  B var;
  var.Set(a);
  var.Set(b);
  var.Set(c);
  var.Set(d);
  return 0;
}

2 个答案:

答案 0 :(得分:4)

标准之间的区别在于:

C ++ 98 [conv.ptr]

  

空指针常量是整数类型的整数常量表达式rvalue,其值为零。

C ++ 11 [conv.ptr]

  

空指针常量是值为零的整数文字或类型为std::nullptr_t的prvalue。

const unsigned char a = 0;满足C ++ 98对整数常量表达式的定义。当然,a不是右值,但似乎左值到左值的转换适用,并且仍然比用户定义的从unsigned charA的转换更好。< / p>

a不是文字,这就是使C ++ 11中的行为不同的原因。

答案 1 :(得分:2)

Clang重现了这个错误,但幸运的是在编译过程中也给出了答案:

overloading_incorrect.cxx:41:13: warning: expression which evaluates
to zero treated as a null pointer constant of type 'B *'
[-Wnon-literal-null-conversion] 
var.Set(a);
        ^

正如NathanOliver在你的帖子中正确提到的那样,只要使用c ++ 11标准(将-std=c++11标志添加到编译器中),这种行为就会消失。