使用相等运算符初始化对象
initialise object with equal operator
在class定义如下命名为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";
当你有
type name = something;
你不是在做赋值,而是你有copy-initialization(不要以为即使它被称为复制也可以移动)。这意味着您的 class 中需要一个构造函数,其参数与 =
.
右侧的参数相匹配
在这种情况下,您没有采用 std::string
、const char*
或 const char[]
的构造函数,因此编译器无法在那里构造实例。
第二种情况有效的原因是
b = "but assignment after declaration is working fine";
没有尝试构造任何东西,因此它调用了有效的赋值运算符,因为
"but assignment after declaration is working fine"
可以转换为std::string
。
如果您希望 class 可以从字符串文字或 cstring 构造,那么您可以以
的形式向其添加构造函数
foo(const char* str) : str(str) {}
你的问题是
foo a = "initialization string";
试图创建一个 foo 类型的对象,但是没有定义接受字符串类型参数的构造函数。
你可以这样定义一个:
foo(const std::string& s) : str(s) {}
foo(const char* s) : str(s) {}
创建对象时,代码 使用构造函数初始化 它,即使创建使用 =
符号也是如此:
struct S {
S(int);
};
S s = 3; // initialization, not assignment
形式上,该初始化使用 S(int)
创建类型为 S
的临时对象,然后使用复制构造函数从临时对象构造对象 s
。
这与处理现有对象的赋值有很大不同:
S s1;
s1 = 3; // assignment
此处,如果 S
定义了赋值运算符,则赋值将使用赋值运算符。这就是原始代码中 b =
行起作用的原因。
对于初学者来说,尽管编译器不会发出诊断消息,但 class 定义中的赋值运算符
class foo{
private:
string str;
public:
foo operator = (string s){
str = s;
}
};
无效,因为它 return 什么都没有,而它具有 return 类型 foo
。
你应该这样写
foo & operator = ( const std::string &s){
str = s;
return *this;
}
由于您既未声明默认构造函数也未声明复制构造函数,因此编译器代替您隐式声明了它们。
所以实际上你的 class 只有两个构造函数。具有以下声明的默认构造函数
foo();
和具有以下声明的复制构造函数
for( const foo & );
在此声明中
foo a = "this initialization throwing an error";
编译器假定在右侧有一个类型为 foo
的对象,您将使用它来创建对象 a
。也就是说,在此声明中,编译器尝试应用隐式创建的复制构造函数。为此,它需要将字符串文字转换为 foo
类型的对象。但是 class 没有转换构造函数,它是一个带有可以接受字符串文字的参数的构造函数。结果编译器发出错误
error: conversion from 'const char [38]' to non-scalar type 'foo'
requested
const char[33]
是声明右侧字符串字面量的类型。
在此代码段中
foo b;
b = "but assignment after declaration is working fine";
首先使用编译器默认构造函数隐式定义的 foo
类型的对象 b
创建,然后在第二个语句中使用显式定义的赋值运算符在 class。根据运算符的定义,它为数据成员 str
分配了一个 std::string
类型的临时对象,该对象是从使用的字符串文字构造的。有可能是因为classstd::string
有对应的转换构造函数
您在第一种情况下所拥有的称为 copy initialization,如文档中所述:
The equals sign, =, in copy-initialization of a named variable is not
related to the assignment operator. Assignment operator overloads have
no effect on copy-initialization.
注意错误。所以可能的解决方案:
首先你可以创建一个构造函数,它接受 std::string
:
foo( const std::string &s );
这将允许您通过以下方式创建 foo
:
foo f( "abc" );
甚至这样:
foo f = foo( "abc" );
但是你的语句仍然会失败,因为:
in addition, the implicit conversion in copy-initialization must
produce T directly from the initializer, while, e.g.
direct-initialization expects an implicit conversion from the
initializer to an argument of T's constructor.
因此,要使您的语句按原样工作,您需要添加此构造函数:
foo( const char *str );
注意:当您添加适当的构造函数时,您不需要定义赋值运算符 - 将使用转换构造函数。并且您的重载赋值运算符应该 return 引用 foo
.
在class定义如下命名为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";
当你有
type name = something;
你不是在做赋值,而是你有copy-initialization(不要以为即使它被称为复制也可以移动)。这意味着您的 class 中需要一个构造函数,其参数与 =
.
在这种情况下,您没有采用 std::string
、const char*
或 const char[]
的构造函数,因此编译器无法在那里构造实例。
第二种情况有效的原因是
b = "but assignment after declaration is working fine";
没有尝试构造任何东西,因此它调用了有效的赋值运算符,因为
"but assignment after declaration is working fine"
可以转换为std::string
。
如果您希望 class 可以从字符串文字或 cstring 构造,那么您可以以
的形式向其添加构造函数foo(const char* str) : str(str) {}
你的问题是
foo a = "initialization string";
试图创建一个 foo 类型的对象,但是没有定义接受字符串类型参数的构造函数。
你可以这样定义一个:
foo(const std::string& s) : str(s) {}
foo(const char* s) : str(s) {}
创建对象时,代码 使用构造函数初始化 它,即使创建使用 =
符号也是如此:
struct S {
S(int);
};
S s = 3; // initialization, not assignment
形式上,该初始化使用 S(int)
创建类型为 S
的临时对象,然后使用复制构造函数从临时对象构造对象 s
。
这与处理现有对象的赋值有很大不同:
S s1;
s1 = 3; // assignment
此处,如果 S
定义了赋值运算符,则赋值将使用赋值运算符。这就是原始代码中 b =
行起作用的原因。
对于初学者来说,尽管编译器不会发出诊断消息,但 class 定义中的赋值运算符
class foo{
private:
string str;
public:
foo operator = (string s){
str = s;
}
};
无效,因为它 return 什么都没有,而它具有 return 类型 foo
。
你应该这样写
foo & operator = ( const std::string &s){
str = s;
return *this;
}
由于您既未声明默认构造函数也未声明复制构造函数,因此编译器代替您隐式声明了它们。
所以实际上你的 class 只有两个构造函数。具有以下声明的默认构造函数
foo();
和具有以下声明的复制构造函数
for( const foo & );
在此声明中
foo a = "this initialization throwing an error";
编译器假定在右侧有一个类型为 foo
的对象,您将使用它来创建对象 a
。也就是说,在此声明中,编译器尝试应用隐式创建的复制构造函数。为此,它需要将字符串文字转换为 foo
类型的对象。但是 class 没有转换构造函数,它是一个带有可以接受字符串文字的参数的构造函数。结果编译器发出错误
error: conversion from 'const char [38]' to non-scalar type 'foo' requested
const char[33]
是声明右侧字符串字面量的类型。
在此代码段中
foo b;
b = "but assignment after declaration is working fine";
首先使用编译器默认构造函数隐式定义的 foo
类型的对象 b
创建,然后在第二个语句中使用显式定义的赋值运算符在 class。根据运算符的定义,它为数据成员 str
分配了一个 std::string
类型的临时对象,该对象是从使用的字符串文字构造的。有可能是因为classstd::string
有对应的转换构造函数
您在第一种情况下所拥有的称为 copy initialization,如文档中所述:
The equals sign, =, in copy-initialization of a named variable is not related to the assignment operator. Assignment operator overloads have no effect on copy-initialization.
注意错误。所以可能的解决方案:
首先你可以创建一个构造函数,它接受 std::string
:
foo( const std::string &s );
这将允许您通过以下方式创建 foo
:
foo f( "abc" );
甚至这样:
foo f = foo( "abc" );
但是你的语句仍然会失败,因为:
in addition, the implicit conversion in copy-initialization must produce T directly from the initializer, while, e.g. direct-initialization expects an implicit conversion from the initializer to an argument of T's constructor.
因此,要使您的语句按原样工作,您需要添加此构造函数:
foo( const char *str );
注意:当您添加适当的构造函数时,您不需要定义赋值运算符 - 将使用转换构造函数。并且您的重载赋值运算符应该 return 引用 foo
.