簡體   English   中英

無法重載operator <<作為成員函數

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM