我有一个班级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;
}
答案 0 :(得分:4)
标准之间的区别在于:
C ++ 98 [conv.ptr]
空指针常量是整数类型的整数常量表达式rvalue,其值为零。
C ++ 11 [conv.ptr]
空指针常量是值为零的整数文字或类型为
std::nullptr_t
的prvalue。
const unsigned char a = 0;
满足C ++ 98对整数常量表达式的定义。当然,a
不是右值,但似乎左值到左值的转换适用,并且仍然比用户定义的从unsigned char
到A
的转换更好。< / 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
标志添加到编译器中),这种行为就会消失。