参考博客:https://blog.csdn.net/e21105834/article/details/115859154
一、问题
写了一段代码相对输出流std::osteam进行操作,可是却一直报错,代码如下:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
ostream os;
stringstream ss1(argv[1]);
os << "ss1:" << ss1.str() << endl;
ss1 >> hex >> supi;
os << "supi:" << supi << endl;
cout << endl;
getchar();
return 0;
}
猛一看,貌似没什么问题,但出现错误如下:
错误:'std :: basic_ostream&lt; _CharT,_Traits&gt; :: basic_ostream()[with _CharT = char;
但是在operator<<重载时却可以使用,让我产生了困惑:
friend std::ostream & operator<<(std::ostream& os, const int& a) {
os << a;
return os;
}
二、错误原因
后来,查看了下std::ostream的构造函数,如下:
public:
//explicit用来防止由构造函数定义的隐式转换
explicit
basic_ostream(__streambuf_type* __sb)
{ this->init(__sb); }
protected:
basic_ostream()
{ this->init(0); }
#if __cplusplus >= 201103L
// Non-standard constructor that does not call init()
basic_ostream(basic_iostream<_CharT, _Traits>&) { }
basic_ostream(const basic_ostream&) = delete;
basic_ostream(basic_ostream&& __rhs)
: __ios_type()
{ __ios_type::move(__rhs); }
// 27.7.3.3 Assign/swap
basic_ostream& operator=(const basic_ostream&) = delete;
basic_ostream&
operator=(basic_ostream&& __rhs)
{
swap(__rhs);
return *this;
}
可以看到ostream类的默认构造函数是保护类型,而带参数的构造函数则是公有的,根据public和protected的功能,我们要定义一个ostream对象,必须要在参数中传入streambuf类型的指针才可以,否则会报编译错误。
下面使用一个例子说明:
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
filebuf buf;
if ( buf.open("/proc/self/fd/1", ios::out) == nullptr )
{
cerr << "stdout open failed" << endl;
return -1;
}
ostream out(&buf);
return 0;
}
总结:std::ostream
,std::istream
或std::iostream
是std::stringstream
,std::fstream
等类的基类。这些类构造函数是保护类型,是不允许拷贝或者赋值的,所以它也不能直接作为返回类型和参数传递,很多时候需要使用引用来进行传递。所以只能实例化其派生类,然后使用引用或者指针来指向实例实现调用。(streambuf也一样,所以上面使用了其子类filebuf)
三、解决办法
最后,还是回到开始的问题,如何解决。这里提供了一种便捷方法,将std::cout控制台输出流实例赋给std::ostream就可以了。
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
ostream &os = std::cout;
stringstream ss1(argv[1]);
os << "ss1:" << ss1.str() << endl;
ss1 >> hex >> supi;
os << "supi:" << supi << endl;
cout << endl;
getchar();
return 0;
}