继承自ifstream

发布于 2024-10-14 02:38:18 字数 1150 浏览 6 评论 0原文

我可以从 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;
}

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

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, 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;
}

I expect it to read the whole file, but it reads just one symbol (which is not the first symbol of the given file)...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一向肩并 2024-10-21 02:38:18

我没有发现您的 extract 函数有问题,但我不明白从 ifstream 派生的意义。

从类派生的目的是重写其虚拟方法,以便当有人传递 istream& 时或 ifstream&到一个函数(通常是运算符>>)中,您的覆盖将被调用。

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

例如,如果您想更改它使用的缓冲区类型,您可以从 basic_streambuf 派生并使用附加的 Streambuf 的简单 istream 或 ostream 对象。

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

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.

葬﹪忆之殇 2024-10-21 02:38:18

您缺少对基本构造函数的调用。我认为你的意思是:

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

}

而不是这个:

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

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

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.

汐鸠 2024-10-21 02:38:18

不要继承 ifstream。如果您需要更改输入流的行为,请继承 streambuf,然后构造一个 <围绕它的 href="http://www.cplusplus.com/reference/iostream/istream/istream/" rel="noreferrer">istream 。如果您只想添加帮助程序,请将它们设置为全局,以便您可以在任何 istream 上使用它们。

也就是说,您的错误在 File 构造函数中:

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

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

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

}

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);
{

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文