2009-08-15 30 views
15

Có rất nhiều thông tin có sẵn khi quá tải operator<< để bắt chước phương thức kiểu toString() chuyển đổi đối tượng phức tạp thành chuỗi. Tôi quan tâm đến việc cũng triển khai nghịch đảo, operator>> để deserialize một chuỗi thành một đối tượng.Nhà điều hành luồng quá tải an toàn >>

Bằng cách kiểm tra nguồn STL, tôi đã thu thập được rằng:

istream &operator>>(istream &, Object &); 

sẽ là chức năng chữ ký chính xác cho deserializing một đối tượng kiểu Object. Rất tiếc, tôi đã thua lỗ về cách triển khai đúng cách này - cụ thể cách xử lý lỗi:

  1. Làm cách nào để chỉ ra dữ liệu không hợp lệ trong luồng? Ném một ngoại lệ?
  2. Trạng thái luồng sẽ là gì nếu có dữ liệu không đúng định dạng trong luồng?
  3. Có nên đặt lại cờ nào trước khi trả về tham chiếu cho chuỗi kết nối không?

Trả lời

18
  1. Làm cách nào để chỉ ra dữ liệu không hợp lệ trong luồng? Ném một ngoại lệ?

Bạn nên đặt bit fail. Nếu người dùng của luồng muốn ngoại lệ được ném, anh ấy có thể định cấu hình luồng (sử dụng istream::exceptions) và luồng sẽ phát theo đó. Tôi sẽ làm điều đó như thế này, sau đó

stream.setstate(ios_base::failbit); 
  1. tiểu bang nào nên dòng được nếu có dữ liệu bị thay đổi trong dòng?

Đối với dữ liệu không đúng định dạng không phù hợp với định dạng bạn muốn đọc, bạn thường nên đặt bit fail. Đối với các lỗi cụ thể của luồng nội bộ, bit bad được sử dụng (chẳng hạn như nếu không có bộ đệm nào được kết nối với luồng).

  1. Có nên đặt lại cờ nào trước khi trả về tham chiếu cho chuỗi kết nối không?

Tôi chưa từng nghe về một điều như vậy.


Để kiểm tra xem luồng có ở trạng thái tốt hay không, bạn có thể sử dụng lớp istream::sentry. Tạo một đối tượng của nó, đi qua các dòng và true (để cho nó không bỏ qua khoảng trắng ngay lập tức). Sentry sẽ đánh giá thành false nếu bit eof, fail hoặc bad được đặt.

istream::sentry s(stream, true); 
if(!s) return stream; 
// now, go on extracting data... 
+1

Cũng đảm bảo bạn kiểm tra bit 'không' trước khi bạn thử làm bất kỳ điều gì. Nếu đã được đặt, chỉ cần trả lại luồng. – KTC

+1

Cảm ơn lời khuyên, đặc biệt là sử dụng bit 'fail' thay vì ngoại lệ. Ngoài việc thiết lập bit không thành công, tôi có phải đảm bảo về nội dung của luồng không? Ví dụ: liệu luồng có bị thay đổi không nếu tôi đặt bit 'không'? –

+0

Đó chính là điều tôi định nói, nhưng bạn đã trả lời nhanh hơn! Tôi muốn thêm rằng câu trả lời đúng được tìm thấy bằng cách tìm kiếm những gì hiện có đang thực hiện, đó là những gì bạn đang mô tả. Ngoài ra, tôi sẽ lưu ý rằng không có những thứ như dữ liệu không đúng định dạng, nhiều như định dạng sai để đọc nó; trong trường hợp đó, bạn muốn đảm bảo biến không thay đổi và (nếu bạn đặt bit không thành công và không phải là bit xấu) không có ký tự nào bị mất khỏi luồng. –

0

Vì cờ, tôi không biết nếu có bất kỳ tiêu chuẩn nào ở đâu đó, nhưng bạn nên đặt lại chúng.

Boost có giấy gói RAII gọn gàng cho rằng: IO State Savers

+0

Tôi không nghĩ rằng điều này được thiết kế để được sử dụng trong trình ngắt nhưng bằng mã người dùng. – AProgrammer

+0

Tôi không thấy sự khác biệt. Chúng cũng hoạt động trên các luồng đầu vào, vì vậy nếu bạn muốn đặt lại cờ cho những gì bạn có thể, tốt hơn là theo cách thủ công.Bộ giải nén ảnh hưởng đến luồng theo những cách kỳ lạ về cơ bản bị hỏng. – Eugene

2

Một số lưu ý thêm:

  • khi thực hiện các nhà điều hành >>, có lẽ bạn nên xem xét sử dụng bufstream và không quá tải khác của nhà điều hành> >;

  • ngoại lệ xảy ra trong quá trình hoạt động phải được dịch sang số không thành công hoặc badbit (thành viên của streambuf có thể ném, tùy thuộc vào lớp được sử dụng);

  • đặt trạng thái có thể ném; nếu bạn đặt trạng thái sau khi nhận được ngoại lệ , bạn nên truyền bá ngoại lệ ban đầu và không phải là ngoại lệ do setstate ném;

  • chiều rộng là trường mà bạn nên chú ý. Nếu bạn đang sử dụng tài khoản , bạn nên đặt lại thành 0. Nếu bạn đang sử dụng toán tử >> để thực hiện các tác phẩm cơ bản, bạn phải tính toán chiều rộng bạn đang chuyển từ số bạn nhận được;

  • xem xét tính đến ngôn ngữ.

Lange và Kreft (Chuẩn C++ IOStream và phá miền địa phương) conver này thậm chí biết thêm chi tiết. Họ cung cấp mã mẫu để xử lý lỗi mất về một trang.

+0

Tại sao bạn đề xuất sử dụng 'bustream' thay vì các quá tải khác (ví dụ:' istream'? Tôi chắc chắn sẽ kiểm tra công việc của Lange và Kreft - âm thanh đó giống như những gì tôi đang tìm kiếm. –

Các vấn đề liên quan