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

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

我想设计一个从文件或控制台读取的对象。如果有命令行参数,则假定此参数是文件名,并且代码将从文件中读取。否则,代码将从标准控制台 cin 读取。由于 ifstream 对象和 cin 都派生自 istream,我想在 class 中存储一个 istream&ifstream 的引用对象或 cin。下面是 class:

的代码
#include <iostream>
#include <fstream>
#include <sstream>

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

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

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

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

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

您可以简单地为 // 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
}