在 C ++ in Plain English,Second Edition (1999)中,书中有一节说" ="可以用来在调用正确的构造函数时进行初始化。就像给出了一个类CStr
和一个构造函数CStr(char*)
一样,这本书说明了这一点:
类似地,最终声明调用构造函数CStr(char *):
CStr name3 = "Jane Doe";
我想用std::string
构造函数尝试相同的操作。我的部分测试代码是:
using namespace std;
class CStr {
private:
string name;
public:
CStr(string s): name(s) {}
};
int main() {
CStr name3 = "Jane Doe";
}
然而,当我编译时,我在name3初始化中遇到错误:
"转换自' const char [9]'到非标量类型' CStr'请求&#34 ;.
为什么没有将CStr :: name初始化为字符串s =" Jane Doe"工作?像string nameTest{"Jane Doe"};
这样的字符串测试有效,所以我认为这也可以。也许这本书已经很久了(它是我现在唯一的一本书),但我认为这个错误更多的是我。
答案 0 :(得分:6)
你的书很旧,但基本上是正确的 [1] 。请注意,"Jane Doe"
不是std::string
,而是const char[9]
(可能会衰减到const char*
)。因此,对于CStr name3 = "Jane Doe";
,需要两个用户定义的转换(即const char*
- > std::string
和std::string
- > CStr
),这不是允许一个implicit conversion。
这也表明,如果CStr
的构造以const char*
为参数,CStr name3 = "Jane Doe";
可以正常工作,因为只需要一个用户定义的转换。
您可以通过添加显式转换来减少一个:
CStr name3 = std::string("Jane Doe");
或直接使用string literal(自C ++ 14开始),类型为std::string
:
CStr name3 = "Jane Doe"s;
为什么没有将CStr :: name初始化为字符串s =“Jane Doe”工作?像
string nameTest{"Jane Doe"};
这样的字符串测试有效,所以我认为这也可以。
你的问题不够明确,无论如何,std::string nameTest{"Jane Doe"};
有效,因为(取决于你的误解)(1)只需要一次隐式转换(const char*
- > std::string
这里;(2)string nameTest{"Jane Doe"};
是直接初始化。
正如@LightnessRacesinOrbit评论的那样,direct initialization(即CStr name3("Jane Doe")
或CStr name3{"Jane Doe"}
(因为C ++ 11))可以正常工作,而CStr name3 = "Jane Doe";
是copy initialization ,他们在某些方面有所不同:
此外,复制初始化中的隐式转换必须 直接从初始化器产生T,而例如, 直接初始化期望从中进行隐式转换 初始化器为T的构造函数的参数。
struct S { S(std::string) {} }; // implicitly convertible from std::string S s("abc"); // OK: conversion from const char[4] to std::string S s = "abc"; // Error: no conversion from const char[4] to S S s = "abc"s; // OK: conversion from std::string to S
这意味着,对于复制初始化,参数Jane Doe
(const char*
)必须直接转换为CStr
;因为需要两个用户定义的转换,所以代码被拒绝。对于直接初始化,可以将Jane Doe
(const char*
)转换为CStr
的构造函数的参数,即首先std::string
,然后CStr::CStr(std::string)
将是调用来构造对象。
[1] "Jane Doe"
是一个c风格的string literal,它是const,从C ++ 11开始,将它分配给char*
是非法的,例如
char * pc = "Jane Doe"; // illegal
const char * pcc = "Jane Doe"; // fine