为什么我不能用`fstream`的实例初始化对`ofstream` /`ifstream`的引用?

Fil*_*efp 15 c++ fstream reference ifstream ostream

介绍

void  read_foo (std::ifstream& out);
void write_foo (std::ofstream& out);
Run Code Online (Sandbox Code Playgroud)

我有这两个函数,其中一个应该从一个文件读取,另一个应该写入一个.

一切都有下面的片段;

std::ifstream ifs ("filename.txt");
read_foo  (ifs);
Run Code Online (Sandbox Code Playgroud)

std::ofstream ofs ("filename.txt");
write_foo (ofs);
Run Code Online (Sandbox Code Playgroud)

问题

但是,如果我尝试使用a std::fstream,那么我可以使用相同的流调用这两个函数,它不会编译,并且编译器会发出大量错误消息.

  • 为什么我不能绑定fstreamifstream&,或ofstream&

Foo.cpp中

#include <fstream>

void  read_foo (std::ifstream& out);
void write_foo (std::ofstream& out);

int main () {
  std::fstream fs ("filename.txt");

   read_foo (fs);
  write_foo (fs);
}
Run Code Online (Sandbox Code Playgroud)

错误(S):


foo.cpp: In function ‘int main()’:
foo.cpp:9:16: error: invalid initialization of reference of type ‘std::ifstream& {aka std::basic_ifstream<char>&}’ from expression of type ‘std::fstream {aka std::basic_fstream<char>}’ read_foo (fs);
^
foo.cpp:3:7: note: in passing argument 1 of ‘void read_foo(std::ifstream&)’ void read_foo (std::ifstream& out);


foo.cpp:10:16: error: invalid initialization of reference of type ‘std::ofstream& {aka std::basic_ofstream<char>&}’ from expression of type ‘std::fstream {aka std::basic_fstream<char>}’
write_foo (fs);
^
foo.cpp:4:6: note: in passing argument 1 of ‘void write_foo(std::ofstream&)’ void write_foo (std::ofstream& out);

Fil*_*efp 25

"长篇故事;简短" - 答案

由于a std::fstream不是源于任何一个std::ofstream,也不是std::ifstream,引用与实例不"兼容"std::fstream.

使用std::istream&std::ostream&,而不是std::ifstream&std::ofstream&(分别).

void write_data (std::ostream&);
void  read_data (std::istream&);
Run Code Online (Sandbox Code Playgroud)

介绍

正如编译器试图告诉你的那样; std::fstream不会继承std::ifstream,因此您无法使用前者的值初始化对后者的引用.

我偶然发现了几个开发人员,他们似乎认为std::fstream,在幕后,是a std::ifstream和a 之间的某种直接合并std::ofstream,并且它是通过两者的推导实现的.

当被问到为什么他们认为是这种情况时,许多人认为答案可以概括为; "因为它有道理,对吧?"


SILLY模仿

想象一下,我们有三个兄弟姐妹; 伊万,欧文约翰,生活在一个家庭里,阅读写作就是一切.

所有的兄弟都带着礼物出生;

  • 伊凡擅长阅读,并且终其一生,他从不做任何其他事情,而且;
  • 欧文有写作的东西,因为他无法阅读,所以很奇怪;
  • 约翰很幸运,兼具阅读写作的技巧.

仅仅因为约翰可以做他兄弟所能做的两件事,并不意味着他们是他的父母 - 毕竟他们是; 他的兄弟.

三兄弟都从其他亲属那里继承了他们的某些特质,而不是彼此.


答案

std::fstreamstd::{i,o}fstream即使它们共享其各自继承树的某些部分,也不是"在...之上"构建的.


iostreams继承可视化

src:http://en.cppreference.com/w/cpp/io


在接受通用代码中的流时,您不应该关心底层流的" 真实 "类型.

如果我们将std :: stringstream,std :: fstreamstd :: ofstream传入我们的函数并将一些输出数据写入流中,这真的很重要吗?不,我们关心的是读/写能力.

我们通过形成到任何一个参考表达这个std::istream,std::ostream或者std::iostream,当我们需要一个流,其能; 分别是读,两者.


(注意:如果不明显:Ivanifstream,Owenofstream,Johnfstream.)

  • [IOStream继承可视化](http://en.cppreference.com/w/cpp/io) (4认同)
  • 很好的解释,它显示了OO的局限性.(使用模板,代码可以工作,因为`fstream`提供了`ifstream`和`ofstream`的方法 (2认同)