我会直截了当地说:
我有一个包含图书名称列表的文本文件。我知道如何阅读文本文件,例如:
string word;
file >> word;
但是,我说有一个名为“word”的课程。是否可以这样做:
word myWord;
file >> myWord;
如果是,那么这个对象将如何宣布?它会读取它包含的第一个公共字符串吗?
感谢您的时间!
答案 0 :(得分:3)
简单的答案是肯定的,你可以做file >> myWord;
因为你为你的班级定义了>>
运算符:
std::ostream&
operator>>( std::ostream& source, Word& word )
{
// ...
return source;
}
有几个注意事项:
此运营商不能成为会员;它必须是一个自由的功能。
(如果是会员,你的班级将是左手
参数。)如果它需要访问私有数据,你可能会
使它成为friend
。
不要忘记错误检查和常规
istream
表示错误。如果遇到输入则无法解析
进入你的班级,你需要设置std::ios::failbit
。 (的
当然,很多时候,你会先前委托给他们
已定义>>
,如果失败,std::ios::failbit
已经存在
已经设定。)
至于你应该在新重载的运算符中做什么, 有几种可能性(可以谨慎使用) 混合的):
您可以调用现有的>>
,例如,字符串或
内置类型。这是迄今为止最简单的,但它假设
你的输入可以很容易地被解析
现有的>>
,这种情况很少见。
您还可以使用未格式化的输入,例如istream::get()
,
这通常与之前的解决方案并行使用,
输入分隔符或其他语法元素之类的东西
你的格式。
或者你可以恢复直接从中读取字节
streambuf
,并解析它们。如果你有这个是合适的
例如,一些全新的类型。如果你走这条路,那就行
不如果您读取文件结尾,则忘记设置eofbit
,即使
你可以成功解析。如果你这样做,你会
还必须在sentry
的顶部创建一个>>
对象,
只有好的才能继续(只有这样
operator>>
std::ios::good
是有意义的std::ios::good()
。你绝不能
如果std::ios::eofbit
尝试读取streambuf中的字符
返回false,您必须随时设置std::ios::good()
读取EOF(将导致所有未来的呼叫
>>
返回false)。这非常重要
我倾向于使用一个小的包装器对象,并通读
它
在所有情况下,您可能必须使用格式
信息:作为一个简单的例子,如果你不想允许
输入中的空白区域,但您仍在使用nows
应设置>>
(并在结束时恢复)。因此,大多数这样的
IOSave
运算符将首先保存格式化状态,然后
最后恢复它。 (这通常通过以下方式完成
failbit
类,无论如何都应该在工具包中。)
而且,如果输入格式中的某些内容不正确,那么
应设置>>
。
举一个简单的例子,考虑一个简单的Complex
std::istream&
operator>>( std::istream& source, Complex& dest )
{
IOSave state( source );
// Skip leading whitespace, depending on formatting options.
if ( (source.flags() & std::ios_base::skipws) != 0 ) {
source >> std::ws;
}
source.unsetf( std::ios_base::skipws );
std::streamsize totalWidth
= std::max( source.width() - 3, std::streamsize(0) ); ;
std::streamsize imagWidth = totalWidth / 2;
std::streamsize realWidth = totalWidth - imagWidth;
if ( source.get() != '(' ) {
source.unget();
source.setstate( std::ios::failbit );
}
double real = 0.0;
source >> std::setw( realWidth ) >> real;
std::numpunct<char> const& np
= std::use_facet<std::numpunct<char>>( source.getloc() );
if ( std::get() != (np.decimal_point() != ',' ? ',' : ';') ) {
source.unget();
source.setstate( std::ios::failbit );
}
double imag = 0.0;
source >> std::setw( imagWidth ) >> imag;
if ( std::peek() != ')' ) {
source.unget();
source.setstate( std::ios::failbit );
}
if ( source ) {
dest = Complex( real, imag );
}
return source;
}
类:
Complex
这是一个非常简单的例子。一个真实的{{1}} 例如,class也会接受a + ib形式的输入。 但它应该让你知道你必须要做的事情 在编写这样的运算符时要考虑。
答案 1 :(得分:1)
当然不是。你必须为你的班级>>
重载word
运算符。您可以将其作为成员函数或非成员函数执行此操作。
要作为非会员超载,您可以写:
fstream& operator >> (fstream& arg1,word& arg2)
{
}
如果此功能需要访问word
的私人成员,您可以使用:
class word{
// somewhere in your class add this line
friend fstream& operator >> (fstream&,word&);
}