【问题标题】:using fstream object created as class member使用作为类成员创建的 fstream 对象
【发布时间】:2013-08-29 22:41:45
【问题描述】:

我有一个像这样在我的类中声明的 fstream 对象(只是一个例子):

class Asd {

  public:
  Asd();

  private:
  std::fstream stream;

};

现在,当调用构造函数时,我想像这样指定 fstream 参数

Asd::Asd() {

  this->stream = std::fstream(file, std::fstream::in);

}

然后在我拥有的所有类函数中使用该流,但它不起作用。 VS 给我的一个错误是:

no accessible path to private member declared in virtual base 'std::basic_ios<_Elem,_Traits>'

所以我阅读了这一点,我发现我不能(或者更确切地说:不应该)复制流,而且我什至不想这样做。有人说可以将它添加到构造函数中:

Asd::Asd() : stream(file, std::fstream::in) {

  ...

}

但它会打印相同的错误,我不知道该怎么办......还有其他人说我必须引用该对象但我不知道如何?我只是想让这个工作,但我想不通:(

编辑:这是完整的错误信息

1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\istream(860): error C2249: 'std::basic_ios<_Elem,_Traits>::operator =' : no accessible path to private member declared in virtual base 'std::basic_ios<_Elem,_Traits>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\ios(177) : see declaration of 'std::basic_ios<_Elem,_Traits>::operator ='
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>          This diagnostic occurred in the compiler generated function 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::operator =(const std::basic_istream<_Elem,_Traits> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream(604): error C2249: 'std::basic_ios<_Elem,_Traits>::operator =' : no accessible path to private member declared in virtual base 'std::basic_ios<_Elem,_Traits>'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\ios(177) : see declaration of 'std::basic_ios<_Elem,_Traits>::operator ='
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]
1>          This diagnostic occurred in the compiler generated function 'std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Traits>::operator =(const std::basic_ostream<_Elem,_Traits> &)'
1>          with
1>          [
1>              _Elem=char,
1>              _Traits=std::char_traits<char>
1>          ]

【问题讨论】:

  • file 是一个 std::string 但即使我在其中放入一个 char const* ,初始化程序也会打印相同的错误。 @Manu343726 我应该总是更喜欢在构造函数体之外构造还是只在这种情况下?我觉得有点别扭,习惯把所有的赋值都放在构造函数里面^^但这并没有说太多,因为我是初学者
  • 我认为在所有情况下你都应该更喜欢初始化列表。我当然会这样做,而且我的大多数构造函数最终都是空的。
  • 我认为错误消息与问题中的代码无关,除了你有一个带有fstream 成员的类。

标签: c++ file class copy fstream


【解决方案1】:

根据您编写的内容,您的构造函数中似乎仍有一个赋值。试试这是否可行:

class Asd {
public:
    Asd(char const* file);

private:
    Asd(Asd&);
    void operator= (Asd&);

    std::ifstream stream;
};

Asd::Asd(char const* file): stream(file) {}

使用成员初始化器列表来构造对象可以避免默认构造它,然后必须在以后设置它。如果你真的想先构造流然后再设置它,你不能使用赋值,因为流既不能复制构造也不能复制赋值。但是,您可以直接打开它,例如:

Asd::Asd(char const* file) { stream.open(file); }

通过使用std::ifstream,不需要将std::ios_base::in(或通过间接派生自std::ios_base 的类(如std::fstream)获取this 值的任何其他变体)传递给构造函数或open()std::ios_base::in 会自动添加到传递给std::ifstream 的构造函数或std::ifstream::open() 的任何内容中。此外,std::ifstream 是一个比std::fstream 更简单的类。它应该更小,构建起来可能更快。

根据 Mooing Duck 的评论,我添加了一个私有复制构造和一个私有赋值运算符,希望编译器会在您尝试复制构造或复制分配 Asd 对象时将您指向其中之一。请注意,当将 传递给按值获取参数的函数或返回Asd 对象时,会尝试复制对象。很有可能您的构造函数中的赋值是编译器抱怨无法复制流的地方,但可能还有其他地方进行了复制尝试。

【讨论】:

  • 实际上,在我看来,当您尝试复制具有其复制构造函数是私有且未定义的成员的对象时,该错误看起来就像 MSVC9 给出的错误。但 MSVC9 不会告诉你副本是在哪里制作的。
  • OP 的错误信息与这里的不同:rise4fun.com/Vcpp/Kd1F 但显然这个版本也没有告诉你副本在哪里。 (看到main 根本不在输出中)
  • 谢谢你……不幸的是,我完全按照你写的做,但错误仍然存​​在。我将不得不对此进行更多研究,但遗憾的是我明天必须这样做,因为我现在没有时间......我将在这个线程中回复希望有好消息:( 编辑:哦,我把完整的错误消息放入我原来的帖子
  • @AurelleDenby:尝试添加私有复制构造函数和复制赋值:您可能正在尝试复制 Asd 对象,该对象由于无法复制内部流而无法工作。
  • @DietmarKühl 谢谢我明天会调查这个问题,我希望在你的帮助下解决它。然后我会在这里回复^^
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 2019-04-09
相关资源
最近更新 更多