我正在尝试创建一个工厂类,该类可以读为好像是一个流对象(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,然后停止)。
答案 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 $