【问题标题】:Can I use a member variable of type ofstream initialized in the class constructor?我可以使用在类构造函数中初始化的流类型的成员变量吗?
【发布时间】:2020-05-14 12:21:36
【问题描述】:

我在声明继承类的构造函数时遇到问题。

class Report{
public:
    string fileName;
    std::ofstream outputFile;

    Report(string fileName, ofstream outputFile) {

        fileName = fileName;
        outputFile = outputFile; //<-- error here
    }

    void returnFile(string, ofstream);

    void Report::returnFile(string name, ofstream file){

         file.open(name);
    }
};

class financialReport: public Report{
public:
    void electorateHappenings();
    void electorialImpact();
    double finances();
    void writetoFile();

    financialReport(string fileName, ofstream outputFile)
    :Report(fileName, outputFile) { } //<-- error here
};

错误发生在第三行最后一行:Report(fileName, outputFile)

此行产生错误:

function "std::basic_ofstream<_CharT, _Traits>::basic_ofstream(const
 std::basic_ofstream<_CharT, _Traits> &) [with _CharT=char, 
_Traits=std::char_traits<char>]" (declared at line 848 of 
"C:\MinGW\lib\gcc\mingw32\9.2.0\include\c++\fstream") cannot be referenced 
-- it is a deleted function

不能创建包含ofstream的构造函数吗?

错误也发生在第 9 行 outputFile = outputFile

谢谢。

【问题讨论】:

  • 参数名称不能与成员变量相同。
  • @gavinb 仍然不起作用
  • @gavinb - 可以。尽管存在风格上的争论。
  • 这是XY problem 的经典例子。你想达到什么目的?您试图以不正确的方式执行此操作并要求修复无效的解决方案。可悲的是,有人已经做出了错误的编译(和工作)方法。

标签: c++ inheritance constructor ofstream


【解决方案1】:

不能复制传递,不能复制一个,但是可以引用传递,在类的初始化器列表中初始化:

Demo

class Report {
public:
    string fileName;
    std::ofstream &outputFile; //reference here

    // reference parameter, and initializer list
    Report(string fileName, ofstream &outputFile) : outputFile(outputFile) {
        fileName = fileName;
    }
    //...
};

financialReport中做同样的事情:

financialReport(string fileName, ofstream& outputFile) : Report(fileName, outputFile) {}
                                         ^

请注意,这是问题中提出的问题的解决方案,正常情况下,但在更深入的分析中,虽然您没有详细说明您想要实现的目标,但我不会走得太远可以说这是一种错误的方法,但很有可能您可以以更好的方式构建您的程序。

【讨论】:

    【解决方案2】:

    是的,你可以,但是错误告诉你不能复制std::ofstream 的对象。

    根据你想做什么,有两种处理方式。

    std::ofstream 的所有权传递给您新创建的对象:

    Report(string fileName, ofstream outputFile) :
        fileName{std::move(outputFile)},
        outputFile{std::move(outputFile)}
    {
    }
    
    //creation of object:
    std::ofstream ofs {"filename.txt"};
    Report report {"filename.txt", std::move(ofs)};
    //ofs is empty here, it's whole content has been transferred to report object
    

    传递对现有std::ofstream 对象的引用:

    class Report{
    public:
      string fileName;
      std::ofstream& outputFile;
    
    Report(string fileName, ofstream& outputFile) :
        fileName{std::move(outputFile)},
        outputFile{outputFile}
    {
    }
    
    //creation of object:
    std::ofstream ofs {"filename.txt}";
    Report report {"filename.txt", ofs};
    //you can use ofs from both here and from inside of report, but 
    //you have to ensure that ofs lives as long as report will use it or else you will enter Undefined Behaviour land
    

    注意:如果你想为类成员和构造函数参数使用相同的名称,你需要像我一样使用member initializer list。如果您决定使用引用,您也必须使用它。

    【讨论】:

      猜你喜欢
      • 2012-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多