我有三个课程:ConsoleInputStream
,ConsoleOutputStream
,ConsoleErrorStream
。所有这些都来自Stream
。
每个流都有虚函数read
和write
;如你所想,当用户尝试使用ConsoleInputStream
的{{1}}成员函数时,会抛出错误。当用户尝试使用write
的{{1}}函数时也会发生相同的情况。
现在是时候展示代码了。
ConsoleOutputStream
但是,当我将write
,// STREAM.HPP
namespace streamlib {
extern ConsoleInputStream stdin_default;
extern ConsoleOutputStream stdout_default;
extern ConsoleErrorStream stderr_default;
extern Stream& stdin;
extern Stream& stdout;
extern Stream& stderr;
} // namespace streamlib
// STREAM.CPP
namespace streamlib {
ConsoleInputStream stdin_default;
ConsoleOutputStream stdout_default;
ConsoleErrorStream stderr_default;
Stream& stdin = stdin_default;
Stream& stdout = stdout_default;
Stream& stderr = stderr_default;
} // namespace streamlib
// MAIN.CPP
int main()
{
streamlib::stdout = streamlib::stdin;
streamlib::stdout.write(); // Still working, but should have thrown error!
}
和stdin
定义为指针而不是引用时,一切都运行良好,即错误按预期抛出。但我不想分配/释放内存并尽可能使用stdout
运算符(我可以吗?)使用普通点运算符。
真实情况当然更加错综复杂:我还有一些来自stderr
的其他类型,只是希望能够快速重载->
,Stream
,{{1具有不同种类的流的流。可以用引用来做吗?
提前致谢!
答案 0 :(得分:3)
您是如何在流上定义作业的?随着 参考声明:
streamlib::stdout = streamlib::stdin;
指定第二个引用引用的内容 第一个提到的。
如果涉及继承,通常是一个坏主意
支持任务;在这种情况下,例如,没有办法
您的ConsoleOutputStream
可以成为
一个ConsoleInputStream
,这意味着正常的帖子
任务条件可能无法满足。通常
解决方案是为基类定义一个私有赋值
运算符,而不是实现它。你也可以从中衍生出来
boost::noncopyable
(但这也会压制
复制 - 您可能想要也可能不想要)。如果你正在使用
C ++ 11,更好的解决方案是标记赋值
运算符已删除。
最后,关于指针:你不需要动态
分配使用指针;你可以初始化一个指针
另一个对象的地址。它似乎工作的原因
指针是分配指针导致指针
被重新安置。如果a
和b
是引用,那么
使用指针的a = b
相当于*a = *b
。
答案 1 :(得分:3)
您无法使用引用执行的操作,因为无法重新分配引用。当您执行此操作时
streamlib::stdout = streamlib::stdin
它对应于解除引用指针的赋值,而不是普通指针。换句话说,如果stdout
和stdin
是指针,则等效代码将是
(*streamlib::stdout) = (*streamlib::stdin)
这会调用Stream
的赋值运算符,并将stdin
传递给stdout
。
解决此问题的一种方法是定义一个可分配的“指针流”,它封装一个指向“实际”流的指针,并在指定时通过指向分配给它的任何流的指针覆盖它。这样可以保留对象语法,让您使用点.
运算符而不是指针解除引用运算符->
。