从iostreams框架派生自己的流






3.80/5 (7投票s)
2002年7月25日
3分钟阅读

92289

987
通过自定义流探索扩展 iostreams 框架。
引言
这是我的 iostreams 三部曲文章中的第三篇。 已经介绍了如何创建插入器、提取器和修改器,接下来我应该解释如何编写一个流。 我将提供两个类,其中一个类覆盖 basic_streambuf
,并提供流实现,另一个类派生自 ostream
,以便为我们提供一个流来将信息传递给我们的底层代码。
想法
本文的基本想法源于有人在 C++ 论坛中提出的一个问题,即关于将 printf
重定向到编辑框。 因此,手头的任务是创建一个流,该流将流输入附加到编辑框的文本。
MFC?
文章代码采用 MFC 对话框项目的形式,但实际的流不使用 MFC。 你可以将头文件复制到任何 Win32 项目中,它应该也能很好地工作。 我怀疑它也应该适用于 WTL,但我根本没有测试过,好吗?
入口点
因为我们是从一个 iostream
类派生的,我们需要覆盖特定的函数,以便我们的代码可以集成到库中。 我们有三个选择。 流操作可能看起来像这样
cout << "this is some text " << 42 << InstanceOfSomeOtherType;
在这个例子中,cout 处理输入的可能位置如下
函数 | 调用位置 |
overflow | 对于传递到流中的每个字符调用一次 |
flush | 当发生刷新时调用,通常通过 endl 或析构函数 |
xsputn | 每个移位运算符调用一次 |
所以我们看到了三种选择。
- 当调用
overflow
时,将每个字符传递到编辑框中 - 当调用
overflow
时,存储每个字符,并在 flush 中一次性传递 - 在
xsputn
中一次传递每个字符串或其他对象
选项 1 应该只被那些执行功能开销低的流使用。 选项 2 最适合昂贵的操作。 选项 3 与选项 1 一样简单,而且更有效。 我们将采用选项 3。
流
基本上,我们在函数中的方法是调用 GetWindowTextLength
来获取窗口中文本的长度,并调用 GetWindowText
来获取字符串,然后我们将其与我们已经拥有的字符串连接起来,并使用(惊喜)SetWindowText
将其放回去。
为了做到这一切,我们需要编辑框的 HWND
,所以我们在两个流对象中提供了一个函数,该函数接受一个 HWND
并返回之前存储的那个。 如果它没有被设置,我们的流什么也不做。
代码如下:
std::streamsize xsputn(const charT * pChar, std::streamsize n) { if (NULL != m_hWnd) { const int nLength = ::GetWindowTextLength(m_hWnd) + 1; char * pText = new char [nLength]; ::memset(pText, 0, nLength); ::GetWindowText(m_hWnd, pText, nLength); std::string s(pText); delete [] pText; s += std::string(pChar); ::SetWindowText(m_hWnd, s.c_str()); return static_cast<std::streamsize>(s.length()); } else return 0; }
现在我们只需要用编辑框的 HWND
初始化我们的流,并使用我们想要传递的文本调用我们的流。 演示程序提供了一个禁用的编辑框,显示已经收到的文本,以及一个启用的编辑框,当你按下提供的按钮时,其内容会被流式传输。
如果你是我写这篇文章的人,我希望它对你有所帮助。 无论如何,我希望它能为你提供更多关于如何使用 iostreams 使你的输入和输出生活更轻松的想法。 在我看来,这是一个很棒的库,但似乎很多人都没有充分利用它。 我希望你发现它对你有用。