在C++中,如何根据运行时条件构造一个引用不同istream对象的对象?

In C++, how to construct an object referencing to different istream object depending on runtime condition?

提问人:user5280911 提问时间:1/16/2020 更新时间:1/16/2020 访问量:175

问:

我想设计一个从文件或控制台读取的对象。如果存在命令行参数,则假定此参数为文件名,代码将从文件中读取。否则,代码将从标准控制台读取。由于 object 和 都是派生自 ,我想在类中存储对 object 或 的引用。以下是该类的代码:cinifstreamcinistreamistream&ifstreamcin

#include <iostream>
#include <fstream>
#include <sstream>

class Reader {
public:
    Reader(std::istream& is) : is(is) {}
private:
    std::istream& is;
};

但是我在尝试根据运行时的条件创建这样的对象时遇到了问题。尝试如下:

int main(int argc, char *argv[]) {
    if (argc > 1) {  //read from file
        std::ifstream in_f(argv[1]);
        if (in_f)
            LineReader reader(in_f);
    }
    else {  //read from console (standard input)
        LineReader reader(std::cin);
    }

    //work on reader ...

    return 0;
}

问题是,对象是在条件语句中构造的。它将在执行出去后消失。但是我需要这个对象在建造后做很多工作。所以我应该在条件之外定义一个对象,但我看不到在条件之前初始化它的方法。我也不知道如何在初始化后“分配”引用,因为引用无法更改。此外,请注意,类不能复制。那么,如果我想存储对 的引用并在运行时根据条件初始化它,您能教我如何编写类吗?我的想法是,用于处理来自控制台或文件的输入的代码完全相同。我想重用单个变量来表示不同类型的输入流。谢谢。ReaderReaderistreamistreamReaderistream

PS:我使用的是C++11,代码将在Windows和Ubuntu中运行。

C++ C++11 参考 初始化 IOSTREAM

评论


答:

2赞 Jarod42 1/16/2020 #1

您可以简单地为以下功能创建一个函数:// work on reader

void do_work(LineReader& reader)
{
    // work on reader
}


int main(int argc, char *argv[]) {
    if (argc > 1) {  //read from file
        std::ifstream in_f(argv[1]);
        if (in_f) {
            LineReader reader(in_f);
            do_work(reader);
        }
    }
    else {  //read from console (standard input)
        LineReader reader(std::cin);
        do_work(reader);
    }
}

或重新组织您的代码以获取以下引用:std::istream

std::istream& get_istream(std::ifstream& in_f, int argc, char* argv[])
{
    if (argc > 1) {  //read from file
        in_f.open(argv[1]);
    }
    if (in_f) {
        return in_f;
    } else {
        return std::cin;
    }
}


int main(int argc, char *argv[]) {
    std::ifstream in_f;
    LineReader reader(get_istream(in_f, argc, argv));

    // work on reader
}

评论

0赞 bartop 1/16/2020
这将很好地工作,但我认为它给我们带来了明显的代码重复
0赞 Jarod42 1/16/2020
@bartop:只是函数调用是相似的。(我不是说将整个代码复制粘贴到 2 个分支中)。
0赞 bartop 1/16/2020
是的,但是添加新的句柄类型将需要复制粘贴istream
1赞 Aconcagua 1/16/2020
但是,这两种方法并不等价,如果无法打开文件,第一种方法不执行任何操作,第二一种方法用作后备。两者都有效,取决于用户需求,但也许值得强调?std::cin
2赞 Aconcagua 1/16/2020
只是化妆品:我个人宁愿将流作为参考传递,并只在那里创建行阅读器......do_work