ถ้าเป็นไปได้เป็นฟังก์ชันที่ไม่ใช่สมาชิกและไม่ใช่เพื่อน
ตามที่อธิบายโดย Herb Sutter และ Scott Meyers เลือกใช้ฟังก์ชันที่ไม่ใช่เพื่อนกับฟังก์ชันของสมาชิกเพื่อช่วยเพิ่มการห่อหุ้ม
ในบางกรณีเช่นสตรีม C ++ คุณจะไม่มีทางเลือกและต้องใช้ฟังก์ชันที่ไม่ใช่สมาชิก
แต่ถึงกระนั้นก็ไม่ได้หมายความว่าคุณจะต้องทำให้ฟังก์ชันเหล่านี้เป็นเพื่อนในชั้นเรียนของคุณฟังก์ชันเหล่านี้ยังสามารถเข้าถึงชั้นเรียนของคุณผ่านทางตัวเข้าถึงชั้นเรียนของคุณ หากคุณประสบความสำเร็จในการเขียนฟังก์ชันเหล่านั้นด้วยวิธีนี้คุณก็จะชนะ
เกี่ยวกับตัวดำเนินการ << และ >> ต้นแบบ
ฉันเชื่อว่าตัวอย่างที่คุณให้ไว้ในคำถามของคุณไม่ถูกต้อง ตัวอย่างเช่น;
ostream & operator<<(ostream &os) {
return os << paragraph;
}
ฉันคิดไม่ออกด้วยซ้ำว่าวิธีนี้ใช้ได้ผลในสตรีมอย่างไร
ต่อไปนี้เป็นสองวิธีในการใช้ตัวดำเนินการ << และ >>
สมมติว่าคุณต้องการใช้วัตถุคล้ายสตรีมประเภท T
และคุณต้องการแยก / แทรกจาก / ลงใน T ข้อมูลที่เกี่ยวข้องของวัตถุของคุณประเภทย่อหน้า
ตัวดำเนินการทั่วไป << และ >> ต้นแบบฟังก์ชัน
สิ่งแรกที่เป็นหน้าที่:
// 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 ;
}
ตัวดำเนินการทั่วไป << และ >> ต้นแบบวิธีการ
สิ่งที่สองเป็นวิธีการ:
// 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 ;
}
โปรดทราบว่าในการใช้สัญกรณ์นี้คุณต้องขยายการประกาศคลาสของ T สำหรับวัตถุ STL สิ่งนี้เป็นไปไม่ได้ (คุณไม่ควรแก้ไข ... )
แล้วถ้า T เป็นสตรีม C ++ ล่ะ?
นี่คือต้นแบบของตัวดำเนินการ << และ >> เดียวกันสำหรับสตรีม C ++
สำหรับ basic_istream ทั่วไปและ basic_ostream
โปรดทราบว่าเป็นกรณีของสตรีมเนื่องจากคุณไม่สามารถแก้ไขสตรีม C ++ ได้คุณต้องใช้ฟังก์ชัน ซึ่งหมายความว่า:
// 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 ;
}
สำหรับ char istream และ ostream
รหัสต่อไปนี้จะใช้ได้กับสตรีมที่ใช้ถ่านเท่านั้น
// 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 แสดงความคิดเห็นเกี่ยวกับความจริงที่ว่ารหัสที่ใช้ถ่านนั้นเป็นเพียง "ความเชี่ยวชาญพิเศษ" ของรหัสทั่วไปที่อยู่ข้างบน แน่นอน Rhys พูดถูก: ฉันไม่แนะนำให้ใช้ตัวอย่างที่ใช้ถ่าน ให้ไว้ที่นี่เท่านั้นเพราะอ่านง่ายกว่า เนื่องจากจะทำงานได้เฉพาะในกรณีที่คุณทำงานกับสตรีมที่ใช้ถ่านเท่านั้นคุณควรหลีกเลี่ยงการใช้งานบนแพลตฟอร์มที่รหัส wchar_t เป็นเรื่องธรรมดา (เช่นบน Windows)
หวังว่านี่จะช่วยได้