为什么std :: ostream的构造函数受到保护? [英] Why the constructor of std::ostream is protected?

查看:115
本文介绍了为什么std :: ostream的构造函数受到保护?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么我不能像这样为我的输出创建一个空"流

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆