[英]Can't Overload operator<< as member function
我試圖重載operator<<
作為成員函數。 如果只是這樣做它的工作原理:
friend ostream& operator<<(ostream& os, const MyClass& myClass);
在我的頭文件和我的MyClass.cc文件中:
ostream& operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
但是,如果我試圖關閉friend
並使其成為成員函數,那么它會抱怨operator<<
只能接受一個參數。 為什么?
ostream& MyClass::operator<<(ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
我在這個問題上讀到它不能成為一個成員函數,但不確定為什么?
當作為成員函數重載時, a << b
被解釋為a.operator<<(b)
,因此它只需要一個顯式參數(將this
作為隱藏參數)。
因為這要求重載是用作左操作數的類的一部分,所以它對普通的ostream
等沒有用。 這需要你的重載是ostream
類的一部分,而不是你的類的一部分。 由於您不允許修改ostream
,因此您不能這樣做。 這只留下全球超載作為替代。
但是,有一個相當廣泛使用的模式,你在全局范圍內重載運算符,但是調用成員函數:
class whatever {
// make this public, or the global overload a friend.
std::ostream &write(std::ostream &dest) const {
// write self to dest
}
};
std::ostream &operator<<(std::ostream &os, whatever const &w) {
return w.write(os);
}
當/如果您想要多態行為時,這尤其有用。 你不能讓重載的運算符本身變成多態,但是你使它成為virtual
函數的成員函數,所以無論如何它都是多態的。
編輯:以(我希望)澄清情況,你可以通過幾種不同的方式做到這一點。 第一個也可能是最明顯的是讓我們的write
成員公開,並讓全局運算符調用它。 由於它是公開的,我們不需要做任何特殊的事情讓操作員使用它:
class myClass {
public:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
// since `write` is public, we can call it without any problem.
return m.write(os);
}
第二種方法是使write
私有,並聲明operator<<
a friend to it it access:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access:
friend std::ostream &operator<<(std::ostream &, myClass const &);
};
std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
第三種可能性幾乎與第二種可能性相似:
class myClass {
// Note this is private:
std::ostream &write(std::ostream &os) const {
// write stuff to stream
return os;
}
// since `write` is private, we declare `operator<<` a friend to give it access.
// We also implement it right here inside the class definition though:
friend std::ostream &operator<<(std::ostream &os, myClas const &m) {
return m.write(os);
}
};
第三種情況在C ++中使用了一個名為“名稱注入”的相當奇怪(並且鮮為人知)的規則。 編譯器知道friend
函數不能成為類的一部分,因此不是定義成員函數,而是將該函數的名稱“注入”到周圍的作用域(在本例中為全局作用域)。 盡管operator<<
是在類定義中定義的,但它根本不是成員函數 - 它是一個全局函數。
您可以將operator<<
重載為成員函數。 但是你不能寫一個成員operator<<
左側有一個ostream,右側是你的類。
當你創建一個(非靜態)成員函數時,有一個隱含的第一個參數,即調用對象。 operator<<
是二進制的,所以它只需要2個參數。 如果你把它作為一個成員函數,你只能給它一個paremeter,因為它已經有一個(調用對象)。 由於該調用對象始終是第一個參數,因此您不可能將輸出運算符編寫為(非靜態)成員(至少不是該特定函數的標准形式),因為對於這種情況,ostream需要成為第一個論點。
可以這樣想:當你想要流到ostream時,你在流對象上調用<<運算符。 而且你不能直接修改ostream的'私有'方法。 因此,您必須創建一個重載版本,並使其成為朋友。
當您在類中創建自己的operator <<方法時,您將創建一個將在您的類上運行的<<方法,而不是ostream對象。 我猜你可以在你的類內部保存一個ostream並流向它,但是你很難寫出像這樣的鏈式語句: a << b << c
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.