在下面定义的类名为foo
class foo{
private:
string str;
public:
foo operator = (string s){
str = s;
}
};
int main(){
foo a = "this initialization throwing an error";
foo b;
b = "but assignment after declaration is working fine";
}
error: conversion from 'const char [38]' to non-scalar type 'foo' requested
上述错误仅在我使用声明为对象实例赋值时引起,但如果我与声明分开分配,则重载的等于=
运算符正常工作。
我想在任何方法中将字符串分配给具有相等运算符的对象
和作为声明,如foo a = "abcd";
答案 0 :(得分:4)
当你有
时type name = something;
您没有进行任务,而是进行了复制初始化(即使它被称为复制也不会有移动)。这意味着您需要在类中使用一个构造函数,该构造函数的参数与=
右侧的参数匹配。
在这种情况下,你没有一个带std::string
,const char*
或const char[]
的构造函数,因此编译器无法在那里构造实例。
第二种情况的原因是
b = "but assignment after declaration is working fine";
不是试图构造任何东西,因此它会调用赋值运算符,因为
"but assignment after declaration is working fine"
可以转换为std::string
。
如果您希望您的类可以从字符串文字或cstring构造,那么您可以以
的形式向其添加构造函数foo(const char* str) : str(str) {}
答案 1 :(得分:2)
第一种情况下的内容称为copy initialization,如文档中所述:
在命名变量的复制初始化中,等号=,不是 与赋值运算符有关。赋值运算符重载有 对复制初始化没有影响。
预测错误。所以可能的解决方案:
首先,您可以创建一个接受std::string
:
foo( const std::string &s );
这将允许您创建foo
:
foo f( "abc" );
甚至是这样:
foo f = foo( "abc" );
但是你的陈述仍然会失败,因为:
此外,复制初始化中的隐式转换必须 直接从初始化器产生T,而例如, 直接初始化期望从中进行隐式转换 初始化器为T&#39的构造函数的参数。
所以要使你的陈述正常工作,你需要添加这个ctor:
foo( const char *str );
注意:添加适当的ctor时,不需要定义赋值运算符 - 将使用转换构造函数。您的重载赋值运算符应返回foo
的引用。
答案 2 :(得分:1)
你的问题是那个
foo a = "initialization string";
尝试创建foo类型的对象,但是没有定义构造函数接受string类型的参数。
你可以这样定义一个:
foo(const std::string& s) : str(s) {}
foo(const char* s) : str(s) {}
答案 3 :(得分:1)
创建对象时,代码使用构造函数初始化,即使创建使用.equals
符号:
=
正式地,初始化使用struct S {
S(int);
};
S s = 3; // initialization, not assignment
创建类型为S(int)
的临时对象,然后使用复制构造函数从临时对象构造对象S
。
与处理现有对象的作业有很大不同:
s
此处,如果S s1;
s1 = 3; // assignment
定义了赋值运算符,则赋值将使用赋值运算符。这就是原始代码中S
行有效的原因。
答案 4 :(得分:1)
对于初学者来说,虽然编译器不会发出诊断消息但是类定义中的赋值运算符
class foo{
private:
string str;
public:
foo operator = (string s){
str = s;
}
};
无效,因为它返回类型为foo
时没有返回任何内容。
你应该像
那样写 foo & operator = ( const std::string &s){
str = s;
return *this;
}
由于您既未声明默认构造函数也未声明复制构造函数,因此编译器隐式声明它们而不是您。
所以实际上你的类只有两个构造函数。具有以下声明的默认构造函数
foo();
以及具有以下声明的复制构造函数
for( const foo & );
在本声明中
foo a = "this initialization throwing an error";
编译器假定在右侧有一个类型为foo
的对象,您将使用它来创建对象a
。在此声明中,编译器尝试应用隐式创建的复制构造函数。为此,需要将字符串文字转换为foo
类型的对象。但是,该类没有转换构造函数,它是一个构造函数,其参数可以接受字符串文字。结果编译器发出错误
错误:从'const char [38]'转换为非标量类型'foo' 请求的
const char[33]
是声明右侧字符串文字的类型。
在此代码段中
foo b;
b = "but assignment after declaration is working fine";
首先使用编译器默认构造函数隐式定义的类型b
创建对象foo
,然后在第二个语句中使用在其中显式定义的赋值运算符。类。从运算符的定义开始,它为数据成员str
分配一个类型为std::string
的临时对象,该对象是根据使用的字符串文字构造的。这是可能的,因为类std::string
具有相应的转换构造函数。