istream类的运算符>>的“返回值”是如何工作的?

3

我试图理解这个陈述:

    int main() {
        fstream inf( "ex.txt", ios::in );
        char c;
        while( inf >> c ) {
            cout << c << ", ";
        }
        return 0;
    }

在上面的while循环中,(inf >> c)返回什么?我下载了gcc源代码并尝试操作,但对我来说太复杂了:(。我查看了C++参考页面,发现它返回对自身的引用。
    istream& operator>> (bool& val );
    istream& operator>> (short& val );
    istream& operator>> (unsigned short& val );
    istream& operator>> (int& val );
    istream& operator>> (unsigned int& val );
    istream& operator>> (long& val );
    istream& operator>> (unsigned long& val );
    istream& operator>> (float& val );
    istream& operator>> (double& val );
    istream& operator>> (long double& val );
    istream& operator>> (void*& val );

    istream& operator>> (streambuf* sb );

    istream& operator>> (istream& ( *pf )(istream&));
    istream& operator>> (ios& ( *pf )(ios&));
    istream& operator>> (ios_base& ( *pf )(ios_base&));

    *** the following functions are not members but GLOBAL functions:

    istream& operator>> (istream& is, char& ch );
    istream& operator>> (istream& is, signed char& ch );
    istream& operator>> (istream& is, unsigned char& ch );

    istream& operator>> (istream& is, char* str );
    istream& operator>> (istream& is, signed char* str );
    istream& operator>> (istream& is, unsigned char* str );

因此,我创建了一个类似的类,假设叫做my_istream:

struct my_istream {
    my_istream& self_ref;
};

int main() {
    my_istream mis;
}

编译时,我遇到了这个错误:

1>c:\users\chan\documents\visual studio 2010\projects\topcoder\topcoder\main.cpp(26): error C2758: 'my_istream::self_ref' : 必须在构造函数基类/成员初始化列表中初始化

然而,在这种情况下,我真的不知道应该将self_ref初始化为什么?当处理链表时,我理解指向自身的指针,我也知道在C++中引用(&)只是C中指针的伪装形式。但是我无法解释这种情况?istream的内部实现是如何工作的?引用如何被评估为true或false?谢谢!

编辑:

struct my_istream {
    my_istream() {
    }

    my_istream& operator >>( int x ) {
        return *this;
    }
};

int main() {
    my_istream mis;
    int x;
    while( mis.operator>>( x ) ) {
        cout << "--";
    }
}

我应该在my_istream类中添加什么内容,以便在while循环中正常工作?

2个回答

2
要返回一个自身引用,只需使用return *this。你实际上不需要声明内部自身引用。你可以有引用成员,但必须在构造函数初始化列表中初始化它们:class Foo { Foo(int& some_int_ref) :my_ref_member(some_int_ref) istream有另一种重载来确定它的布尔值。
这是一个可链接成员的例子(像operator >>,但在这种情况下只是一个普通函数),并为类赋予布尔值(尽管后者是一个值得单独讨论的复杂主题)。
#include <iostream>

class X {
    bool B;
public:
    X() :B(false) { }
    X& toggle() { B = !B; return *this; }
    operator void*() { return B ? this : 0; }
};

int main()
{
    X x;

    x.toggle().toggle().toggle();
    if (x)
        std::cout << "true!" << std::endl;
}

编辑:我不想在这个答案中深入探讨operator booloperator void *的区别,但这个旧的stackoverflow问题应该为您提供很好的参考:为什么在我强制转换为“long”时会调用“operator bool()”?


感谢清晰的解释。那么,如果我想要实现类似于istream类的技术,我应该在我的类中提供什么? - roxrook

1
上面的 while 循环中,( inf >> c ) 返回什么?
void*。该循环测试解析为 while (inf.operator void*() != NULL)。
引用如何被评估为 true 或 false?
但支持转换为 bool 或可转换为 bool 的内容。
istream 的内部实现实际上是怎样工作的?
它只是返回对它本身的引用(return *this),这样就可以支持链式操作。

所以我必须提供void*()运算符才能将该语句放入while循环中吗? - roxrook
你不需要显式地调用它(因为你已经看到了)。这是一个转换运算符。在这里,C++会自动调用它,因为它发现对象被用于布尔上下文中。如果有一个 operator bool,它会调用那个,但是没有,所以它调用了可转换为布尔值的 operator void*。理解这些东西很重要,因为它可能会给你带来麻烦。 :) - Mud

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接