C++ 2 个字符串流的包装器("dialogue"模仿)
C++ wrapper around 2 stringstreams ("dialogue" imitation)
我目前正在为两个流编写包装器。最后,我想模仿与Person
的对话,以使我的代码清晰且易于使用。
class Person
{
public:
void process();
private:
std::stringstream _request;
std::stringstream _response;
}
使用Person daniel;
std::stringstream answer;
daniel << "Hello" << std::endl; // f.e std::endl means end of the phrase
daniel << "How" << "are you";
daniel << "doing?";
daniel >> answer;
daniel.process();
std::cout << "Daniel says: " << answer;
// or
std::cout << "Daniel says: " << daniel;
我觉得我可以通过重载<<
和>>
操作符来实现它,但我被卡住了。我从未将流用于这些目的。我在谷歌上搜索了很多,显然还是不能理解基本的东西。
简而言之
std::ostream& operator<<(std::ostream& o, const person& p)
{
output << p._response.rdbuf();
return (output);
}
std::istream& operator>>(std::istream& i, person& p)
{
p._request << i.rdbuf();
// internal process() call probably will be better
return (p._request);
}
一些例子确实会很棒,但我绝对会对那些让我走出僵局的粗略想法感到高兴。
老实说,我不明白你为什么要这样做,但我想这是某种练习或家庭作业。无论如何,实现这个功能有一些微妙之处,我怀疑你自己无法弄清楚,所以这里是可行的解决方案。
#include <iostream>
#include <sstream>
class Person {
public:
void process() {
// Let's see what we've got in `_request`
std::cout << _request.rdbuf() << std::endl;
// Do some processing to produce correponding _response
// In this example we hardcode the response
_response << "I'm fine, thanks!";
}
private:
std::stringstream _request;
std::stringstream _response;
// Make them all friends so that they can access `_request` and `_response`
friend Person& operator<<(Person& p, std::string const& s);
friend Person& operator<<(Person& p, std::ostream& (*f)(std::ostream&));
friend std::ostream& operator<<(std::ostream &o, Person& p);
friend Person& operator>>(Person& p, std::string& s);
};
Person& operator<<(Person& p, const std::string& s) {
p._request << s;
return p;
}
// Notice this peculiar signature, it is required to support `std::endl`
Person& operator<<(Person& p, std::ostream& (*f)(std::ostream&)) {
p._request << f;
return p;
}
// Somewhat conventional stream operator overload (in terms of signature)
std::ostream& operator<<(std::ostream &o, Person& p) {
o << p._response.rdbuf();
return o;
}
Person& operator>>(Person& p, std::string& s) {
// NOTE: This will read not the whole `_reponse` to `s`, but will stop on
// the first whitespace. This is the default behavior of `>>` operator of
// `std::stringstream`.
p._response >> s;
return p;
}
#include <iostream>
#include <sstream>
class Person {
public:
void process() {
// Let's see what we've got in `_request`
std::cout << _request.rdbuf() << std::endl;
// Do some processing to produce correponding _response
// In this example we hardcode the response
_response << "I'm fine, thanks!";
}
private:
std::stringstream _request;
std::stringstream _response;
// Make them all friends so that they can access `_request` and `_response`
friend Person& operator<<(Person& p, std::string const& s);
friend Person& operator<<(Person& p, std::ostream& (*f)(std::ostream&));
friend std::ostream& operator<<(std::ostream &o, Person& p);
friend Person& operator>>(Person& p, std::string& s);
};
Person& operator<<(Person& p, const std::string& s) {
p._request << s;
return p;
}
// Notice this peculiar signature, it is required to support `std::endl`
Person& operator<<(Person& p, std::ostream& (*f)(std::ostream&)) {
p._request << f;
return p;
}
// Somewhat conventional stream operator overload (in terms of signature)
std::ostream& operator<<(std::ostream &o, Person& p) {
o << p._response.rdbuf();
return o;
}
Person& operator>>(Person& p, std::string& s) {
// NOTE: This will read not the whole `_reponse` to `s`, but will stop on
// the first whitespace. This is the default behavior of `>>` operator of
// `std::stringstream`.
p._response >> s;
return p;
}
值得一提的是,就你想要实现的功能而言,你的第一次尝试是完全错误的。这可以归结为这样一个事实,即您似乎遵循了关于流操作符重载的传统教程,而这里的方法应该有所不同,以便实现所需的功能。特别要注意建议的流操作符重载的签名。
此外,您必须添加更多的重载以支持其他输入类型,例如int
。本质上,您必须添加更多的重载,类似于std::basic_ostream提供的开箱即用的重载。特别要注意最后一个:
basic_ostream& operator<<(basic_ostream& st,
std::basic_ostream& (*func)(std::basic_ostream&));
这个家伙是用来支持std::endl
的。请注意,我已经为Person
添加了类似的过载,以便std::endl
能够正常工作(见下文)。其他的重载,比如基本类型的重载,留给您作为练习。
你一开始就想要的那个
int main() {
Person daniel;
daniel << "Hello" << std::endl;
daniel << "How " << "are you";
daniel << " doing?" << std::endl;
// We are ready to process the request so do it
daniel.process();
// And Daniel's answer is...
std::cout << "Daniel says: " << daniel << std::endl;
return 0;
}
阅读反应:Alternative Way
这个有点笨拙和麻烦,基本上是Person& operator>>(Person& p, std::string& s)
重载实现中的注释(见上文)的结果。
int main() {
Person daniel;
daniel << "Hello" << std::endl;
daniel << "How " << "are you";
daniel << " doing?" << std::endl;
// We are ready to process the request so do it
daniel.process();
// And Daniel's answer is...
std::string part1;
std::string part2;
std::string part3;
// Will read "I'm"
daniel >> part1;
// Will read "fine,"
daniel >> part2;
// Will read "thanks!"
daniel >> part3;
std::cout << "Daniel says: " << part1 << " " << part2 << " " << part3 << std::endl;
return 0;
}
rdbuf()不返回字符串。你应该调用str()从stringstream中获取std::string。为了访问该类的私有属性,需要将这两个函数声明为该类的友元。
class Person
{
public:
void process();
friend std::ostream& operator<<(std::ostream& o, const person& p);
friend std::istream& operator>>(std::istream& i, person& p);
private:
std::stringstream _request;
std::stringstream _response;
}
std::ostream& operator<<(std::ostream& o, const person& p)
{
o << p._response.str();
return (o);
}
std::istream& operator>>(std::istream& i, person& p)
{
i >> p._request;
// internal process() call probably will be better
return i;
}
相关文章:
- 如何用 gcc 或 clang 模仿_mm256_loadu_epi32?
- 如何模仿派生到基本指针自动投射?
- 如何使用 strspn 模仿 std::string 的find_first_not_of
- 在C++中模仿类似 Golang 的界面
- 我如何使用MFC C 模仿办公风格
- 我可以在C++中做/模仿这样的事情(部分覆盖)吗?
- 长整数的意外模仿行为
- 模仿 QApplication::p alette() 基于颜色样式的行为
- 如何安全地关闭C 模仿外壳
- 是否可以通过与EasyLogging 相同的方式来创建一个C 类,以模仿STD :: COUT语法
- C++ 模仿向量的链接列表
- 这个JS语法可以用C++模仿吗?
- 有人知道一个模仿帕斯卡"range array"的类吗?
- 如何在 ncurses 中模仿 TTY 行为?当我们到达底部时,向上推动屏幕上的所有线条
- 是否有模仿临时变量的C++变量类型
- 我怎样才能用OpenCV模仿Matlab的medfilt2
- 使用我自己的list.sort()逻辑,试图模仿其他来源,为什么我会因为看似正确的格式而出错
- 模仿conditional_back_inserter这样的东西的最佳方式
- 在 VBA 中模仿 std::map<string、std::list<string> >
- C++ 2 个字符串流的包装器("dialogue"模仿)