我有以下课程:
#include <iostream>
#include <string>
using namespace std;
class CLS
{
int value;
string str_value;
public:
CLS(int param) { value = param; }
CLS(string param)
{
str_value = param;
}
};
int main()
{
CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5"; // Error: invalid conversion from 'const char*' to 'int'
}
我搜索了没有运气的错误原因。
使用字符串文字构造是否正确? 如果不是,为什么? 如果是的话,我的代码出了什么问题?
我正在使用gcc 5.3和Code :: Blocks 16.1。
答案 0 :(得分:11)
首先,"4"
不是std::string
,而是const char[2]
。然后
CLS c("4");
为direct initialization,我们会检查CLS
的构造函数是否初始化c
。这里会选择CLS::CLS(string)
,因为const char[]
可以通过用户定义的转化(即std::string
)隐式转换为std::string::string(const char*)
。
CLS d = "5";
是copy initialization,
(强调我的)
- 如果
T
是类类型,并且other
类型的cv-nonqualified版本不是T
或来自T
,或{{1} }}是非类型,但T
的类型是类类型,用户定义的转换序列,可以从other
的类型转换为other
(或者T
派生的类型,如果T
是类类型并且转换函数可用),则检查并通过重载决策选择最佳的类型。
这意味着需要用户定义的转换序列才能将T
转换为const char[2]
。即使CLS
也可以转换为const char[]
,std::string
也可以转换为std::string
,但只允许在一个implicit conversion sequence中进行一次用户定义的转换。这就是它被拒绝的原因。
(强调我的)
隐式转换序列按以下顺序组成:
1)零个或一个标准转换序列;
2)零或一个用户定义的转换;
3)零个或一个标准转换序列。
顺便说一句:如果你把它改为使用CLS
作为初始化表达式,那么它就可以正常工作了。 e.g。
std::string
答案 1 :(得分:8)
CLS a(2);
CLS b = 3;
CLS c("4");
CLS d = "5";
a
和c
初始化为direct initialisation。另一方面,b
和d
使用copy initialisation。
不同之处在于,对于复制初始化,编译器会搜索(单个)用户定义的转换(在d
的情况下)char const *
(这有点不准确,请参见答案结束) CLS
,而对于直接初始化,尝试了所有构造函数,其中CLS(std::string)
可以使用,因为可以使用转换std::string(char const *)
。
<强>详情:强>
"5"
是(C)字符串文字。它的类型是char const [2]
。首先,搜索用户定义的从该类型到CLS
的转换。由于找不到任何内容,因此会应用从Type[N]
到Type *
(Type
= char const
和N
= 2
)的标准转换,在char const *
中。然后编译器尝试查找用户定义的转换为CLS
。因为它找不到一个,并且没有更多可以尝试的标准转换,编译失败。