如何创建行为类似于流对象的工厂

时间:2019-05-10 17:13:39

标签: c++ stream factory

我正在尝试创建一个工厂类,该类可以读为好像是一个流对象(sstream看起来最相似,但是我可能错了),能够提供预定数量的值然后停止(失败状态(eof),并且与cin参考兼容。我想避免使用其他诸如boost的库。

#include <sstream>
#include <iostream>

class Factory : public std::stringstream {
    int count;
public:
    Factory() : count{ 0 } {}
    Factory & operator>>(int &x) {
        if (count < 2)
            x = count++;
        else
            this->setstate(std::ios::failbit);
        return *this;
    }
};

int main(int argc, char *argv[]) {
    int a;
    Factory f;
    char choice;
    std::cout << "Read from (c)in or (f)actory? ";
    std::cin >> choice;
    std::istream &ss = (choice == 'f') ? f : std::cin;
    while (ss >> a)
        std::cout << "a = " << a << std::endl;
    return 0;
}

输入“ f”时,不会读取任何内容。如果将while循环更改为直接从f而不是ss读取,则它将按预期工作(读取0、1,然后停止)。

1 个答案:

答案 0 :(得分:0)

除了评论中的健康批评之外,让我们考虑一下这里发生的事情:

std::istream &ss = (choice == 'f') ? f : std::cin;
while (ss >> a)

istreame引用ss正在调用operator>>(int &)(不包括ADL)。因此,即使ss指向您的Factory类(通常不是工厂),它仍将调用其基运算符,因此选择f永远无效。

如果您想实现预期的目标,那么必须在基类中将operator>>定义为多态的(声明为virtual)。但这不是。

因此您的方法失败了。如果您想实现类(作为流)和其他基于std::istream的多路分解(仅针对您的情况),则应将这种方法重新设计为以下形式:

#include <sstream>
#include <iostream>

class Factory {
    int count;
    std::istream * is_ptr;
    static std::stringstream dummy;
public:
    Factory(std::istream &is = dummy): count{0}, is_ptr(&is) {}
    operator bool(void) { return count < 5; }
    Factory & operator>>(int &x) { 
        if(is_ptr == &dummy)                   // it's me being called
         { x = count++; return *this; }
        *is_ptr >> x;                          // otherwise, calling a proxy 
        return *this;
    }
};
std::stringstream Factory::dummy;


int main(int argc, char *argv[]) {
    int a;
    Factory f, c(std::cin);
    char choice;
    std::cout << "Read from (c)in or (f)actory?\n";
    std::cin >> choice;
    //choice = 'f';
    Factory &ss = (choice == 'f') ? f : c;
    while (ss >> a)
        std::cout << "a = " << a << std::endl;
    return 0;
}

选择为'f'的输出:

Read from (c)in or (f)actory?
f
a = 0
a = 1
a = 2
a = 3
bash $ 

选择为'c'的输出:

Read from (c)in or (f)actory?
c
123
a = 123
098765
a = 98765
^C
bash $