我在C ++中有一个方便的类,可以使用double
或char*
进行初始化。一切都按预期工作,除了参数为零的一种情况。
struct Var {
Var (double src) {}
Var (char *src) {}
};
int main(int argc, char* argv[]) {
Var A = 123;
Var B = "abc";
Var C = 0; <- Error: conversion from 'int' to 'Var' is ambiguous
}
之前我使用的是int
而不是double
,并且由于某种原因它没有问题。
如何解决这个问题?
PS:我知道我可以使用(double)0
或仅0.0
,但有没有办法让0
被接受为双?< / p>
答案 0 :(得分:11)
您可以通过添加第三个构造函数来消除歧义,该构造函数需要int
并委托给double
版本(需要C ++ 11):
struct Var {
Var (double src) {}
Var (const char *src) {}
// ^^^^^ should be const
Var (int src) : Var {static_cast<double>(src)} {}
};
但是,通过更改char*
构造函数以取代std::string
并使用直接初始化,可以更轻松地解决此问题。
答案 1 :(得分:7)
在C ++中,文字0
的类型为int。你不能改变它是一个整数的任何东西,不添加至少一个小数点。 (虽然没有实际需要在点之后写数字)
回答关于为什么电话与123
明确无误但与0
含糊不清的隐含问题:
初始化A
时,它很好,因为没有从int到指针的隐式转换(在这种情况下为char*
)。
当您第二次使用int初始化C
时,您使用了0
,文字0
可以隐式转换为指针(某些遗留行为,在C之前) ++ 11提供了nullptr
字面值。
所以,简而言之:
int * a = 0; // legal;
int * b = 2; // ILLEGAL;
初始化C
时需要进行一次转换以将参数提供给两个可用构造函数中的任何一个(并且两个转换具有相同的排名),调用是不明确的。
为了使其明确无误,您应该将int文字转换为double((double)0
),使用双重文字(0.
),或者添加一个带int的构造函数。
使用最后一个解决方案,构造函数采用int
是完全匹配,因此它是另一个需要转换的重载(这就是为什么会被选中)的更好匹配。
编辑。请注意,这里应该接受 TartanLlama 答案,因为它是最好的C ++实践:采用C风格字符串的构造函数应该采用std::string
。由于存在从C样式字符串到std::string
的隐式转换,因此调用几乎没有变化:
Var B("abc");
但是你会将你的类接口与指针细节隔离开来。