我读到,当提供适合转换构造函数或操作数时,C ++编译器能够隐式转换类型。 我实际上找到了看起来像这样的示例代码:
class Dog{
private:
string name;
public:
Dog(string n):name(n){} //This as the converting constructor
}
int main(){
Dog d = "rover";
}
每当我运行此代码时,编译器都会抛出一条错误消息:
从'const char [6]'转换为非标量类型'Dog'请求 狗d ="流浪者&#34 ;;
编译时我添加编译器选项-std=c++11
,所以它不应该是关于C ++版本的,对吧?
我在互联网上找到的例子(至少对我而言)看起来完全相同,所以我不知道这里出了什么问题。
我对此主题的输入来自此视频:
Convert constructor and overloading operators - thenew moston
答案 0 :(得分:35)
您还需要了解您正在使用复制初始化而不是直接初始化。
They are different,您需要了解他们与explicit
的关系以及他们之间的关系。您需要了解chains of conversions work的方式,最多涉及一次用户定义的转换。
Dog d1 ("rover");
Dog d2 = "rover";
d2案例尝试将文字转换为狗,然后将其复制(移动)到d2。但这将是双转换:const char*
到string
,然后是string
到Dog
。
d1案例构造d1将参数传递给构造函数,因此只有一个转换const char*
到string
。 (在这两种情况下,促销const char [6]
到const char*
也在那里,但不会计入"只有一个"允许,属于不同的类别。)
复制初始化不指定"流浪者"作为构造函数的参数。它说"这里有东西,但这里需要Dog
"。 here 是copy-init声明语法的右侧,而不是任何可识别的函数。编译器比必须找到合法的转换。
在direct-init情况下, 只是为函数(构造函数)提供参数。编译器将您提供的内容转换为声明的参数类型。
答案 1 :(得分:26)
注意"rover"
不是std::string
,而是const char[6]
(末尾为空字符)(可能会衰减到const char*
),以使{ {1}}工作,Dog d = "rover";
需要转换为"rover"
,然后转换为std::string
。
但user-defined conversion在一次隐式转换中不会被认为是两次。
(强调我的)
在隐式转换的第二阶段调用用户定义的转换函数,该函数由零或一个转换构造函数或零或一个用户定义的转换函数组成。
您可以将Dog
转换为"rover"
明确以使其有效。
std::string
答案 2 :(得分:17)
您需要另一个构造函数,允许您从const char*
:
Dog(const char* n):name(n){}
请记住,"rover"
不是std::string
,并且不会推断出类型隐式使用转换构造函数。正如@songyuanyao在回答中提到的,转换只会进行一次。
另一种选择是写:
Dog d = std::string("rover");