继承自ifstream

时间:2011-01-24 09:39:07

标签: c++ inheritance ifstream

我可以从ifstream继承并从我的派生类中读取文件,如下所示:

#include <iostream>

using namespace std;

const string usage_str = "Usage: extract <file>";

class File: public ifstream
{
public:
    explicit File(const char *fname, openmode 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;
}

我希望它能读取整个文件,但它只读取一个符号(这不是给定文件的第一个符号)......

3 个答案:

答案 0 :(得分:7)

不要从ifstream继承。如果您需要更改输入流的行为,请从streambuf继承,然后围绕它构建istream。如果您只想添加帮助器,请将它们设置为全局,以便您可以在任何istream上使用它们。

那就是说,你的错误在File构造函数中:

File::File(const char *fname, openmode mode)
{
    ifstream(fname, mode);
}

这构造了一个(未命名的)ifstream,然后立即关闭它。您想调用超类构造函数:

File::File(const char *fname, openmode mode)
  : ifstream(fname, mode);
{

}

答案 1 :(得分:1)

我没有看到你的提取函数存在问题,但我没有从ifstream派生出来。

从类派生的目的是覆盖其虚拟方法,以便当有人通过istream&amp;或ifstream&amp;进入一个函数(通常是运算符&gt;&gt;),你的覆盖被调用。

与STL集合不同,流确实使用层次结构和v表,但新手通常会错误地理解这个概念。

例如,如果你想改变它使用的缓冲区类型,你将从basic_streambuf派生出来,并使用一个简单的istream或ostream对象,并附带你的streambuf。

通过从iostream或streambuf派生新类,您无法更改打印或读取对象的方式,也无法扩展iomanips,您必须在流式传输的对象周围使用包装类。

答案 2 :(得分:0)

您缺少对基础构造函数的调用。我想你的意思是:

File::File(const char *fname, openmode mode) : ifstream(fname, mode)
{

}

而不是:

File::File(const char *fname, openmode mode)
{
    ifstream(fname, mode);
}

现在你可能正在阅读一些未初始化的内存。第二个(当前)代码只是在堆栈上创建一个ifstream的新实例并立即销毁它。