2012-05-21 21 views
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; 
} 

Vui lòng giải thích cho tôi, đoạn mã sau hoạt động như thế nào? nếu (fin == NULL) {break; }C++, đọc tệp bằng ifstream

vây là một đối tượng trên ngăn xếp, không phải là con trỏ để nó không thể trở thành NULL. Tôi không thể tìm thấy hàm operator == quá tải trong lớp ifstream. Vì vậy, tôi không thể hiểu được đoạn mã này hoạt động như thế nào.

Trả lời

5

Lớp ifstream có số operator void *() (or operator bool() in C++11). Đây là những gì được gọi khi bạn kiểm tra (fin == NULL).

Kiểm tra fin == NULL phải chính xác giống như thử nghiệm fin.fail().

+0

Cảm ơn bạn rất nhiều. Câu trả lời của bạn rất hữu ích. – Yoh0xFF

3

Các lớp cơ sở của istreamostream có chức năng chuyển đổi ẩn , cho phép chúng được sử dụng dưới dạng giá trị logic; trong pre-C++ 11, chuyển đổi tiềm ẩn là void*. Nó không bao giờ là ý định rằng kết quả của chuyển đổi này được sử dụng như một con trỏ và mã như fin == NULL cho thấy sự hiểu biết về C++ và luồng tiêu chuẩn cực kỳ kém. Cách thành ngữ viết vòng lặp đầu tiên sẽ được xác định một constructor mặc định và một operator>> cho Person, và sau đó viết:

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

(Và trong khi tôi đang ở đó: bạn thực sự cần kiểm tra giá trị trả về của fin.close(), và không quay trở lại 0 nếu nó không thành công:.

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

)

+0

Mặc dù tôi đồng ý rằng có thể thực hành tốt nhất để làm điều đó, tôi đã ** không bao giờ thấy mã kiểm tra xem việc đóng có thành công hay không và điều chỉnh giá trị trả về. Cá nhân, tôi không bao giờ gọi 'close' dù sao, dựa vào RAII để thay thế - nhưng may mắn là tôi có thể lấy đi bằng mã viết không làm IO mạnh mẽ. –

+0

@KonradRudolph: Tôi đoán dựa vào RAII ngụ ý rằng hàm hủy không kiểm tra xem liệu việc đóng có thành công hay không. Không có phương tiện để vận chuyển một điều kiện lỗi đến người gọi (trừ khi bạn sử dụng các biến toàn cầu). –

+0

@Frerich Tất nhiên. Như tôi đã nói, tôi có thể lấy đi bằng cách làm IO không mạnh mẽ. Lười biếng, tôi biết, nhưng nó làm cho mã đơn giản hơn và sạch hơn. –

2

Đây không phải như thế nào là st reams có nghĩa vụ phải được sử dụng. Đúng, điều này (không may!) Biên dịch và thậm chí là điều "đúng". Nhưng đừng viết mã như thế này. Ai viết mã này có lẽ nghĩ rằng họ thông minh.

Nhưng những gì họ thực sự làm là phá vỡ sự mong đợi của các lập trình viên C++ bằng cách giới thiệu một API mới, độc đáo, không có lợi thế thực sự.

Mã này khởi tạo đối tượng thuộc loại Person từ luồng đầu vào. Thật không may, bằng cách làm điều này, mã sẽ quên cơ hội kiểm tra lỗi trong khi đọc đối tượng. Điều này không tốt. Một đối tượng nên không phải có một hàm tạo chấp nhận luồng đầu vào, nó sẽ quá tải operator>>.

+0

Chơi người bảo vệ quỷ ở đây: Tôi nghĩ rằng việc truyền một luồng tới một nhà xây dựng có ý nghĩa hoàn hảo. Bạn có thể sử dụng các ngoại lệ để báo hiệu lỗi, và bạn tránh được vấn đề có khả năng của các đối tượng chưa được khởi tạo (không giống như thay thế được đề xuất của bạn, cho phép xây dựng một đối tượng nhưng không sử dụng 'toán tử >>'). –

+0

@Frerich Về nguyên tắc, tôi hoàn toàn đồng ý với bạn. Đó cũng là lý do tại sao tôi nói rằng đây là một lập trình viên thông minh, thay vì James nghĩ rằng đó là một người không biết gì về dòng suối. Nhưng nó vẫn phá vỡ kỳ vọng và có lẽ không phải là một ý tưởng hay trong việc xây dựng C++ trên đầu trang của thư viện luồng hiện tại. Các luồng có thể được thực hiện tốt hơn nhiều, nhưng sau đó xây dựng một thư viện riêng, không xây dựng trên đầu trang của một mô hình hiện có hoạt động khác nhau. –