Inheriting from ifstream
Can I inherit from ifstream and read the file from my derived class like this:
#include <iostream>
using namespace std;
const string usage_str = "Usage: extract <file>";
class File: public ifstream
{
public:
explicit File(const char *fname, openm开发者_如何学JAVAode mode = in);
void extract(ostream& o);
};
File::File(const char *fname, openmode mode)
{
ifstream(fname, mode);
}
void File::extract(ostream& o)
{
char ch;
char buf[512];
int i = 0;
while (good()) {
getline(buf, sizeof(buf));
o<<buf;
i++;
}
cout<<"Done "<<i<<" times"<<endl;
}
void msg_exit(ostream& o, const string& msg, int exit_code)
{
o<<msg<<endl;
exit(exit_code);
}
int do_extract(int argc, char *argv[])
{
cout<<"Opening "<<argv[1]<<endl;
File f(argv[1]);
if (! f)
msg_exit(cerr, usage_str, 1);
f.extract(cout);
return 0;
}
int main(int argc, char *argv[])
{
if (argc < 2)
msg_exit(cout, usage_str, 0);
do_extract(argc, argv);
return 0;
}
I expect it to read the whole file, but it reads just one symbol (which is not the first symbol of the given file)...
Don't inherit from ifstream. If you need to change an input stream's behavior, inherit from streambuf, then construct an istream
around it. If you just want to add helpers, make them global so you can use them on ANY istream.
That said, your bug is in the File constructor:
File::File(const char *fname, openmode mode)
{
ifstream(fname, mode);
}
This constructs an (unnamed) ifstream, then immediately closes it. You want to call the superclass constructor:
File::File(const char *fname, openmode mode)
: ifstream(fname, mode);
{
}
I don't see an issue with your extract function but I do not get the point of deriving from ifstream.
The purpose of deriving from a class is to override its virtual methods so that when someone passes an istream& or ifstream& into a function (usually operator>>) your override gets called.
Unlike STL collections, streams do use a hierarchy and v-tables but newcomers will typically get the concept wrong.
For example if you want to change the buffer type it uses you would derive from basic_streambuf and use a simple istream or ostream object with your streambuf attached.
Changing the way the objects are printed or read is not something you can do by deriving a new class from iostream or streambuf, nor can you extend the iomanips, you have to use wrapper classes around the objects you are streaming.
You are missing a call to the base constructor. I think you mean this:
File::File(const char *fname, openmode mode) : ifstream(fname, mode)
{
}
instead of this:
File::File(const char *fname, openmode mode)
{
ifstream(fname, mode);
}
Right now you are probably reading contents of some uninitialized memory. The second (current) code just creates a new instance of ifstream on the stack and destroys it right away.
精彩评论