Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何阻止编译器删除我的函数_C++_File - Fatal编程技术网

C++ 如何阻止编译器删除我的函数

C++ 如何阻止编译器删除我的函数,c++,file,C++,File,当我在重载运算符的末尾添加return语句时,编译器会抛出一个错误。它说: “File::Fileconst File&”被隐式删除,因为默认定义的格式不正确 但是,当我删除return语句和类型说明符时,没有问题 class File : public Document { private: fstream mainFile; string drive, folder, fileName, fullPath; protected: public: File(strin

当我在重载运算符的末尾添加return语句时,编译器会抛出一个错误。它说:

“File::Fileconst 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;
    }

};
此运算符正在按值返回其结果。也就是说,通过拷贝

问题是该文件包含一个std::fstream成员,该成员本身有一个已删除的副本构造函数。它不能被复制。std::fstream表示可能打开的文件。复制打开的文件的概念完全没有意义,因此无法复制文件流对象,并且由于该文件本身无法复制,因为它包含不可复制的类成员,这就是编译错误的原因。试图复制不可复制的类

省略return语句会导致一个未定义的行为,即声明为返回文件而不返回任何内容的函数

这都是因为赋值运算符的实现存在几个基本问题。作业操作员应:

取一个常量参数

返回对其自身实例的引用,并

把这个还给我

为了实现具有预期语义的赋值运算符,应该将其声明为

File &operator=(const File &a)
通过返回来完成它的工作

    return *this;
此运算符正在按值返回其结果。也就是说,通过拷贝

问题是该文件包含一个std::fstream成员,该成员本身有一个已删除的副本构造函数。它不能被复制。std::fstream表示可能打开的文件。复制打开的文件的概念完全没有意义,因此无法复制文件流对象,并且由于该文件本身无法复制,因为它包含不可复制的类成员,这就是编译错误的原因。试图复制不可复制的类

省略return语句会导致一个未定义的行为,即声明为返回文件而不返回任何内容的函数

这都是因为赋值运算符的实现存在几个基本问题。作业操作员应:

取一个常量参数

返回对其自身实例的引用,并

把这个还给我

为了实现具有预期语义的赋值运算符,应该将其声明为

File &operator=(const File &a)
通过返回来完成它的工作

    return *this;

复印操作员的签名应为:

File & operator=(File const &);
编译器正在抱怨返回a;因为操作符声明它返回的是一个对象,而不是一个引用,所以需要复制。但是mainFile是一个std::fstream,它本身没有提供复制构造函数,因此编译器无法为您生成复制构造函数。您自己没有提供复制构造函数,因此文件对象是不可复制的。这就是为什么返回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;
}

请注意,我们还通过常量引用获取参数;这允许从常数为的文件对象进行复制分配,否则,您将无法执行。此外,赋值运算符通常应返回对赋值目标的引用,该引用是*this,而不是a.

复制运算符的签名应为:

File & operator=(File const &);
编译器正在抱怨返回a;因为操作符声明它返回的是一个对象,而不是一个引用,所以需要复制。但是mainFile是一个std::fstream,它本身没有提供复制构造函数,因此编译器无法为您生成复制构造函数。您自己没有提供复制构造函数,因此文件对象是不可复制的。这就是为什么返回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;
}

请注意,我们还通过常量引用获取参数;这允许从常数为的文件对象进行复制分配,否则,您将无法执行。此外,赋值运算符通常应该返回对赋值目标的引用,该目标是*this,而不是a。

顺便说一句,this->符号是不必要的。仅当局部变量或参数与成员同名时才使用它。您可以更改参数和局部变量以避免此->。此外,此->对于执行类方法不是必需的。在检查find的结果时,更喜欢使用std::string::npos而不是-1。您正在尝试返回传入引用的副本。该类不知道如何构造副本。您需要编写一个复制构造函数。默认定义的格式不正确,因为默认定义是按成员复制的,并且无法复制fstream对象。因此,编译器不知道如何处理mainFile member.BTW,不需要this->符号。仅当局部变量或参数与成员同名时才使用它。您可以更改参数&local
避免此问题的变量->。此外,此->对于执行类方法不是必需的。在检查find的结果时,更喜欢使用std::string::npos而不是-1。您正在尝试返回传入引用的副本。该类不知道如何构造副本。您需要编写一个复制构造函数。默认定义的格式不正确,因为默认定义是按成员复制的,并且无法复制fstream对象。因此,编译器不知道如何处理mainFile成员。“复制”打开的文件的概念是完全没有意义的-我可以看到这样的论点,即复制文件句柄dup在语义上是复制fstream的有效解释。所以“无意义”这个词可能太强了。尽管如此,该功能并没有提供-无论如何,通过一个copy-ctor…所以我尝试将参数设置为const,但编译器抛出一个错误,表示我正在丢弃限定符。但是,在代码内部,const输入是一个R值,因此不应更改。一旦R值可以用第二个=符号改变,那么函数应该关闭,不要担心const指示符。所有其他方法,getDrive等,都必须是const方法本身。因为根据定义,它们不应该修改它——它们是getter,仅此而已——它们本身必须是const方法。避免bug的最好方法是以一种大多数bug都会立即导致编译失败的方式来编写代码,而不是以一种奇怪的运行时行为来结束,这种行为最终会浪费大量的时间试图弄清楚。而且,作为额外的奖励,C++语言的所有标准特性,如复制构造函数将自动正确工作。“复制”打开文件的概念完全没有意义。我可以看到复制文件句柄DUP的说法将是对复制FScript的语义有效的解释。所以“无意义”这个词可能太强了。尽管如此,该功能并没有提供-无论如何,通过一个copy-ctor…所以我尝试将参数设置为const,但编译器抛出一个错误,表示我正在丢弃限定符。但是,在代码内部,const输入是一个R值,因此不应更改。一旦R值可以用第二个=符号改变,那么函数应该关闭,不要担心const指示符。所有其他方法,getDrive等,都必须是const方法本身。因为根据定义,它们不应该修改它——它们是getter,仅此而已——它们本身必须是const方法。避免bug的最好方法是以一种大多数bug都会立即导致编译失败的方式来编写代码,而不是以一种奇怪的运行时行为来结束,这种行为最终会浪费大量的时间试图弄清楚。而且,作为额外的奖励,C++语言的所有标准特性,如复制构造函数将自动正确工作。在复制任何内容之前执行以下操作:File&operator=File const&a{if&a!=this{…}返回*this;}确定。所以我把passbyreference指示器放在返回值中,它工作正常。但这不意味着函数可以访问文件在内存中的位置吗?@RaymondIacobacci,这是正确的。无法直接复制流对象。然而,有一些解决办法。我认为这是一种反模式。将对象复制到自身是调用者的一个语义错误,不值得为此进行优化—只是为了确保仍然满足后置条件。@cdhowie:自赋值很少见,但并非不可能。一个人可以把作业写得不需要检查,但这通常需要复制一份,而不考虑自己的作业。如果复制操作通常比检查自我分配更昂贵,那么在这些情况下,检查自我分配有助于提高性能。别忘了检查&a!=在复制任何内容之前执行以下操作:File&operator=File const&a{if&a!=this{…}返回*this;}确定。所以我把passbyreference指示器放在返回值中,它工作正常。但这不意味着函数可以访问文件在内存中的位置吗?@RaymondIacobacci,这是正确的。无法直接复制流对象。然而,有一些解决办法。我认为这是一种反模式。将对象复制到自身是调用者的一个语义错误,不值得为此进行优化—只是为了确保仍然满足后置条件。@cdhowie:自赋值很少见,但并非不可能。一个人可以把作业写得不需要检查,但这通常需要复制一份,而不考虑自己的作业。如果复制操作通常比自我分配检查更昂贵,则在这些情况下,自我分配检查有助于提高性能。