Nếu có thể, như các chức năng không phải thành viên và không bạn bè.
Theo mô tả của Herb Sutter và Scott Meyers, thích các chức năng không phải là thành viên không phải bạn bè với các chức năng thành viên, để giúp tăng đóng gói.
Trong một số trường hợp, như các luồng C ++, bạn sẽ không có lựa chọn và phải sử dụng các hàm không phải là thành viên.
Tuy nhiên, điều đó không có nghĩa là bạn phải biến các hàm này thành bạn của các lớp của mình: Các hàm này vẫn có thể truy cập lớp của bạn thông qua các hàm truy cập lớp của bạn. Nếu bạn thành công trong việc viết các chức năng này theo cách này, thì bạn đã thắng.
Giới thiệu về nguyên mẫu toán tử << và >>
Tôi tin rằng các ví dụ bạn đưa ra trong câu hỏi của bạn là sai. Ví dụ;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
Tôi thậm chí không thể bắt đầu nghĩ làm thế nào phương pháp này có thể hoạt động trong một luồng.
Dưới đây là hai cách để thực hiện các toán tử << và >>.
Giả sử bạn muốn sử dụng một đối tượng giống như luồng loại T.
Và bạn muốn trích xuất / chèn từ / vào T dữ liệu có liên quan của đối tượng thuộc loại Đoạn.
Các nguyên mẫu hàm toán tử << và >> chung
Đầu tiên là chức năng:
// T << Paragraph
T & operator << (T & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// T >> Paragraph
T & operator >> (T & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return p_oInputStream ;
}
Các nguyên mẫu chung của toán tử << và >>
Thứ hai là phương thức:
// T << Paragraph
T & T::operator << (const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return *this ;
}
// T >> Paragraph
T & T::operator >> (const Paragraph & p_oParagraph)
{
// do the extraction of p_oParagraph
return *this ;
}
Lưu ý rằng để sử dụng ký hiệu này, bạn phải mở rộng khai báo lớp T. Đối với các đối tượng STL, điều này là không thể (bạn không cần phải sửa đổi chúng ...).
Và nếu T là một luồng C ++ thì sao?
Dưới đây là các nguyên mẫu của cùng một toán tử << và >> cho các luồng C ++.
Đối với basic_istream và basic_ostream chung
Lưu ý rằng đó là trường hợp của luồng, vì bạn không thể sửa đổi luồng C ++, bạn phải thực hiện các chức năng. Có nghĩa là một cái gì đó như:
// OUTPUT << Paragraph
template <typename charT, typename traits>
std::basic_ostream<charT,traits> & operator << (std::basic_ostream<charT,traits> & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> Paragraph
template <typename charT, typename traits>
std::basic_istream<charT,traits> & operator >> (std::basic_istream<charT,traits> & p_oInputStream, const CMyObject & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
Đối với char istream và Ostream
Đoạn mã sau sẽ chỉ hoạt động đối với các luồng dựa trên char.
// OUTPUT << A
std::ostream & operator << (std::ostream & p_oOutputStream, const Paragraph & p_oParagraph)
{
// do the insertion of p_oParagraph
return p_oOutputStream ;
}
// INPUT >> A
std::istream & operator >> (std::istream & p_oInputStream, const Paragraph & p_oParagraph)
{
// do the extract of p_oParagraph
return p_oInputStream ;
}
Rhys Ulerich nhận xét về thực tế mã dựa trên char nhưng là "chuyên môn hóa" của mã chung ở trên nó. Tất nhiên, Rhys đã đúng: Tôi không khuyên bạn nên sử dụng ví dụ dựa trên char. Nó chỉ được đưa ra ở đây vì nó đơn giản hơn để đọc. Vì nó chỉ khả thi nếu bạn chỉ làm việc với các luồng dựa trên char, nên bạn nên tránh nó trên các nền tảng nơi mã wchar_t là phổ biến (tức là trên Windows).
Hy vọng điều này sẽ giúp.