2016-11-08 33 views
2

In C++ in Plain English,Second Edition(1999),书中有一段说“=”可以用来在调用正确的构造函数时进行初始化。等给出一类CStr和构造CStr(char*),书中这样说:为什么此C++成员初始值设定项列表不起作用?

同样,最后宣言调用构造函数CStr的(字符*):

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'请求“。

为什么不初始化CStr :: name为字符串s =“Jane Doe”?像string nameTest{"Jane Doe"};这样的字符串测试工作,所以我认为这也会起作用。也许这本书的旧版(这是我现在唯一的书),但我认为这个错误更多。

+2

顺便说一句,自从99年以来C++发生了很大的变化。自那时起,两项新标准添加了一堆新功能,并删除了一些过时的标准。 –

+1

实际上,我的书桌上仍有该书的副本。非常有用的书可以作为C标准库的快速参考。 – user4581301

+1

顺便说一下,你可以使用带有'CStr(char *)'构造函数的字符串文字的时代已经过去了。字符串文字不能转换为'char *'类型,只能转换为'const char *'。 – AnT

回答

6

你的书很旧,但基本上正确[1]。请注意,"Jane Doe"不是std::string,它是const char[9](并可能衰减到const char*)。因此,对于CStr name3 = "Jane Doe";,需要两个用户定义的转换(即,const char*std::stringstd::stringCStr),这在一个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"};是直接初始化。

As @LightnessRacesinOrbit评论,direct initialization(ieCStr name3("Jane Doe")CStr name3{"Jane Doe"}(因为C++ 11))将正常工作,而CStr name3 = "Jane Doe";copy initialization是,它们在某些点是不同的:

另外,在复制初始化的隐式转换必须 产生Ť直接从初始化器,而例如 直接初始化期望从 初始值设定项到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 Doeconst char*)转换为参数CStr的构造函数(即std::string),然后调用CStr::CStr(std::string)构造对象。


[1] "Jane Doe"是一个C语言风格string literal是常量,由C++ 11是非法的其分配给char*,例如

char * pc = "Jane Doe";   // illegal 
const char * pcc = "Jane Doe"; // fine 
+2

或者'CStr name3(“Jane Doe”)'或者'CStr name3 {“Jane Doe”}' –

+0

你的回答很好,但是这个难题的缺点是这是复制初始化与其他类型不同的一种方式。 –

+0

@LightnessRacesinOrbit OP的误解对我来说还不够清楚,无论如何,我试图添加相关的解释。 – songyuanyao

相关问题