为什么std :: ostream的构造函数受到保护? [英] Why the constructor of std::ostream is protected?
问题描述
为什么我不能像这样为我的输出创建一个空"流
Why I can't just create an "empty" stream for my output like this
std::ostream out;
?
在Linux下使用 libstdc ++
的 clang 3.4
和 gcc 4.8.1
,此行显然是非法的,我真的不明白为什么,我的意思是为什么我不能仅凭空创建一个流并像我想要的那样使用它?请注意, std :: ofstream out;
可以100%正常运行.我只是不明白这背后的逻辑.如果您认为创建后我可以仅使用此缓冲区并与其他带有 copyfmt
的缓冲区共享一个公共缓冲区,那么这甚至更陌生,因此我的 std :: ostream <真正不需要/code>从创建对象开始就被初始化为正确的东西.
This rows is apparently illegal with both clang 3.4
and gcc 4.8.1
under linux with libstdc++
, I really don't get why, I mean why I can't just create a stream out of nowhere and use it like I want to ? notice that std::ofstream out;
is 100% ok instead. I just don't get the logic behind this.
This is even stranger if you consider that after the creation I can just use this buffer and share a common buffer with other buffers with copyfmt
so there is no real need for my std::ostream
to be initialized to something right from the creation of the object to be useful.
请不要偏离这一点,我不需要 stringstreams
,我需要 ios
流,这是因为我必须做的事情以及由于这些方法和他们提供的属性.
Please don't deviate from this, I don't need stringstreams
, I need ios
streams because of what I have to do and because of the methods and the properties that they are offering.
推荐答案
我也承认我也不理解.我找不到 std :: istream
的默认构造函数,我认为如果要创建双向流,则需要一个,由于 std :: ios_base
的奇怪工作方式:构造函数不初始化任何东西,但是派生类必须在其类中显式调用 std :: ios_base :: init
构造函数.当涉及多重继承时双向IO,其中类别是从两者派生的 std :: istream
和 std :: ostream
),我希望只有最派生类以调用 std :: ios_base :: init
.(在 std :: iostream
, std :: ios_base :: init
将被调用两次.)实际上,在标准中查找之前,我打算回答默认构造函数受到保护,因为它没有调用 std :: ios_base :: init
并直接使用它,而是比派生类中的结果大,将导致未初始化流.
I'll admit that I don't understand it either. I can't find any
default constructor at all for std::istream
, and I would think
you would want one if you want to create a bidirectional stream,
because of the strange way std::ios_base
works: the
constructor does not initialize anything, but the derived
class must call std::ios_base::init
explicitly in its
constructor. When multiple inheritance is involved (i.e.
bidirectional IO, where the class derives from both
std::istream
and std::ostream
), I would expect only the most
derived class to call std::ios_base::init
. (In
std::iostream
, std::ios_base::init
will be called twice.)
In fact, before looking it up in the standard, I was about to
answer that the default constructor was protected, because it
didn't call std::ios_base::init
, and using it directly, rather
than in a derived class, would result in an uninitialized
stream.
无论如何,您眼前的问题有一个简单的解决方案:
Anyhow, your immediate problem has a simple solution:
std::ostream out( NULL );
另外:您以后需要设置其接收器的功能是 rdbuf()
的非常量版本,而不是 copyfmt()
的非常量版本. rdbuf()
是用于读取和设置指向 streambuf
的指针, copyfmt()
复制格式标记,但不指向 streambuf
的指针.
Also: the function you need to set up its sink later is the
non-const version of rdbuf()
, not copyfmt()
. rdbuf()
is
used to read and to set the pointer to the streambuf
,
copyfmt()
copies the formatting flags, but does not touch
the pointer to streambuf
.
因此您可以执行以下操作:
So you can do things like:
std::ostream out( NULL );
// ...
std::filebuf fileBuffer;
if ( filenameGiven ) {
fileBuffer.open( filename.c_str(), std::ios_base::out );
}
if ( fileIsOpen() ) {
out.rdbuf( &fileBuffer );
} else {
out.rdbuf( std::cout.rdbuf() );
}
(我经常这样做.实际上,我认为这是通常的做法.当您不预先知道是否输出到文件时的习惯用法或 std :: cout
.)
(I do this a lot. In fact, I thought that it was the usual
idiom when you didn't know up front whether to output to a file
or to std::cout
.)
还有另一个更正: rdbuf
的非常量版本调用 clear()
,因此您不必.(我知道我是在不调用 clear()
的情况下完成此操作的,但是当我看到 init
设置了 badbit
...)
And yet another correction: the non-const version of rdbuf
calls clear()
,
so you don't have to. (I knew I'd done this without calling clear()
, but
when I saw that init
set badbit
...)
无论如何:总结是:通常最好将指针传递给有效的指针.streambuf到 std :: ostream
的构造函数,但是如果不能,那就是完全有效,可以传递空指针,并在以后使用设置有效指针 rdbuf()
.否则,答案就是错误的.
Anyhow: the summary is: it's usually preferrable to pass a pointer to a valid
streambuf to the constructor of std::ostream
, but if you can't, it's
perfectly valid to pass a null pointer, and set a valid pointer later using
rdbuf()
. And the answers which say otherwise are simply wrong.
这篇关于为什么std :: ostream的构造函数受到保护?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!