使用相等运算符初始化对象
initialise object with equal operator
在下面定义的名为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";
这样的声明<</strong>
当你有
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) {}
在第一种情况下,您所拥有的称为复制初始化,如文档中所述:
命名变量的复制初始化中的等号 = 不是 与赋值运算符相关。赋值运算符重载具有 对复制初始化没有影响。
纠结错误。所以可能的解决方案:
首先,您可以创建一个接受std::string
的构造函数:
foo( const std::string &s );
这将允许您通过以下方式创建foo
:
foo f( "abc" );
甚至这个:
foo f = foo( "abc" );
但是您的语句仍然会失败,因为:
此外,复制初始化中的隐式转换必须 直接从初始值设定项生成 T,而例如 直接初始化需要从 T 构造函数参数的初始值设定项。
因此,为了使您的语句按原样工作,您需要添加此 CTOR:
foo( const char *str );
注意:当您添加适当的 ctor 时,您不需要定义赋值运算符 - 将使用转换构造函数。并且重载的赋值运算符应返回对foo
的引用。
创建对象时,代码会使用构造函数对其进行初始化,即使创建使用 =
符号也是如此:
struct S {
S(int);
};
S s = 3; // initialization, not assignment
从形式上讲,该初始化使用 S(int)
创建类型 S
的临时对象,然后使用复制构造函数从临时对象构造对象s
。
有很大不同,赋值处理已经存在的对象:
S s1;
s1 = 3; // assignment
在这里,赋值将使用赋值运算符(如果S
定义了赋值运算符(。这就是原始代码中的b =
行起作用的原因。
你的问题是
foo a = "initialization string";
尝试创建 Foo 类型的对象,但是没有定义接受字符串类型参数的构造函数。
你可以像这样定义一个:
foo(const std::string& s) : str(s) {}
foo(const char* s) : str(s) {}
对于初学者来说,虽然编译器不会发出诊断消息,但类定义中的赋值运算符
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
的对象。但是,该类没有转换构造函数,该构造函数是具有可以接受字符串文本的参数的构造函数。结果编译器发出错误
错误:从"常量字符 [38]"转换为非标量类型"FOO" 要求
const char[33]
是声明右侧字符串文本的类型。
在此代码片段中
foo b;
b = "but assignment after declaration is working fine";
首先,使用编译器默认构造函数隐式定义的创建类型foo
的对象b
,然后在第二条语句中使用类中显式定义的赋值运算符。根据运算符的定义,它为数据成员str
分配一个类型为 std::string
的临时对象,该对象是从使用的字符串文本构造的。这是可能的,因为类std::string
具有相应的转换构造函数。
- C++使用整数的压缩数组初始化对象
- 如何使用cudaMallocManaged在指针位置初始化对象?(C++)
- 在 c++ 中初始化对象
- C++ 手动分配和初始化对象
- 使用运算符"="在C++中用值初始化对象
- 当我不需要数据库中的所有值时,如何部分初始化 c++ 对象?
- 如何初始化对象数组?
- 在C++中使用默认构造函数初始化对象的不同方法
- 使用默认构造函数初始化对象的不同方法
- 是否可以在编译时初始化对象的 C 样式函数指针,以便它调用对象的成员函数?
- 如何在线程中初始化对象,然后在其他地方使用它?
- 在没有默认构造函数时使用垃圾数据初始化对象
- 如果在 C++ 构造函数中以错误的顺序初始化对象数据,会发生什么类型的错误
- 初始化对象以在 C++08 中作为参数传递的首选语法是什么?
- 在 c++ 中复制对未初始化对象的引用
- 在成员变量在另一个文件中发生更改后,调用与初始化对象分开的函数
- 在不放置新运算符的情况下,在预分配的内存上使用虚函数初始化对象 - 这可能吗?如果没有,为什么
- 复制 CTOR 与赋值运算符以初始化对象(性能)
- 当您通过分配初始化C 对象时会发生什么
- 获取未初始化对象成员的地址是否定义良好?