6
class Person {
private:
    string firstName;
    string lastName;
public:
    Person() {}

    Person(ifstream &fin) {
       fin >> firstName >> lastName;
    }

    void print() {
       cout << firstName
           << " "
           << lastName
           << endl;
    }
};

int main() {
    vector<Person> v;
    ifstream fin("people.txt");

    while (true) {
        Person p(fin);
        if (fin == NULL) { break; }
        v.push_back(p);
    }

    for (size_t i = 0; i < v.size(); i++) {
       v[i].print();
    }

    fin.close();
    return 0;
}

请你能解释一下,下面的代码片段是如何工作的?if (fin == NULL) { 休息; }

fin 是堆栈上的对象,而不是指针,因此它不能变为 NULL。我无法在 ifstream 类中找到重载的 operator== 函数。所以我不明白这个片段是如何工作的。

4

3 回答 3

5

该类ifstream有一个operator void *()(或operator bool()在 C++11 中)。这就是你测试时所说的(fin == NULL)

测试fin == NULL应该与测试完全相同fin.fail()

于 2012-05-21T07:01:47.197 回答
3

istream和的基类ostream具有隐式转换函数,可以将它们用作布尔值;在 C++11 之前的版本中,隐式转换为void*.

从未打算将此转换的结果用作指针,并且类似代码fin == NULL显示对 C++ 和标准流的理解极差。编写第一个循环的惯用方式是定义一个默认构造函数和一个 operator>>for Person,然后编写:

Person p;
while ( fin >> p ) {
    v.push_back( p );
}

(当我这样做时:你真的应该测试 的返回值 ,如果失败fin.close()则不返回:0

fin.close();
return fin ? EXIT_SUCCESS : EXIT_FAILURE;

.)

于 2012-05-21T08:29:08.307 回答
2

这不是应该使用流的方式。没错,这(不幸的是!)编译甚至做了“正确”的事情。但是不要写这样的代码。编写此代码的人可能认为他们很聪明。

但他们真正做的是通过引入一个新的、非常规的 API 来打破 C++ 程序员的期望,但没有真正的优势。

Person此代码从输入流初始化类型对象。不幸的是,这样做,代码放弃了在读取对象时测试错误的机会。这不好。一个对象不应该一个接受输入流的构造函数,它应该重载operator>>

于 2012-05-21T08:33:52.340 回答