当我在重载return
的末尾添加operator=
语句时,编译器会抛出错误。它说:
' File :: File(const File&)'被隐式删除,因为默认定义是不正确的
但是,当我删除return
语句(和类型说明符)时,没问题。
class File : public Document {
private:
fstream mainFile;
string drive, folder, fileName, fullPath;
protected:
public:
File(string d, string f, string fn, string txt = "NULL") : Document(txt) {
drive = d;
folder = f;
fileName = fn;
if(fileName.find(".txt") == -1) {
fileName.append(".txt");
}
fullPath = drive + ":/" + folder + "/" + fileName;
mainFile.open(fullPath.c_str());
mainFile << txt;
}
File() : Document() {
drive = folder = fileName = "NULL";
fullPath = drive + ":/" + folder + "/" + fileName;
}
File operator = (File & a) {
this->getDrive() = a.getDrive();
this->getFolder() = a.getFolder();
this->getFileName() = a.getFileName();
this->getText() = a.getText();
this->fileName = a.fileName;
return a;
}
};
答案 0 :(得分:4)
File operator = (File & a) {
此运算符按值返回其结果。也就是说,通过副本。
问题是File
包含std::fstream
成员,该成员本身有一个已删除的复制构造函数。它无法复制。 std::fstream
表示可能打开的文件。 “复制”打开文件的概念完全没有意义,因此无法复制文件流对象,因此File
本身无法复制,因为它包含一个不可复制的类成员,这就是原因编译错误。试图复制不可复制的类。
抛出return
语句会导致一个未定义的行为,该行为被声明为返回File
而不返回任何内容。
这完全是因为您实现赋值运算符的几个基本问题。赋值运算符应该:
获取const
参数。
将 引用 返回给自己的实例,
返回*this
。
为了实现具有预期语义的赋值运算符,它应该声明为
File &operator=(const File &a)
并通过返回
完成其工作 return *this;
答案 1 :(得分:1)
您的复制操作员的签名应为:
File & operator=(File const &);
编译器抱怨return a;
,因为运算符声明它返回一个对象而不是引用 - 因此需要复制a
。但mainFile
是std::fstream
,它不提供自己的复制构造函数,因此编译器无法为您生成复制构造函数。您自己没有提供复制构造函数,因此File
对象是不可复制的。这就是返回a
时出错的原因。
正确的实施方式是:
File & operator=(File const & a) {
this->getDrive() = a.getDrive();
this->getFolder() = a.getFolder();
this->getFileName() = a.getFileName();
this->getText() = a.getText();
this->fileName = a.fileName;
return *this;
}
请注意,我们还通过const引用获取参数;这允许从File
对象进行复制分配,这些对象是const(否则,你不能)。此外,赋值运算符通常应该返回对赋值目标的引用(*this
,而不是a
)。