2011-12-04 63 views
10

我想在我的一個類中超載運算符< <。 簽名是這樣的:C++ - 必須在頭文件中定義朋友函數嗎?

friend std::ostream& operator<<(std::ostream& os, const Annuaire& obj) 

當我試圖把它定義在.cpp文件中,它說的是,運營商< <正是以1種說法,然而,當我在.H定義它,它編譯/工作正常。

這是我在.cpp文件中定義它:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... } 

是否有任何與友元函數需要在頭文件中定義?

+0

你必須得到'ostream'和'istream'權利...... –

+0

是的,你的朋友是istream和一個在CPP是ostream的,如果是故意的,你將需要2項朋友聲明和2所定義,如果沒有的話,根據你想要輸入還是輸出流來修復一個或另一個 –

+0

謝謝,無論如何,這是一個複製粘貼錯誤。 – Pacane

回答

9

它可以在CPP文件中定義,但它需要至少是宣佈在頭文件中,否則要使用它只是將所有的地方看到流本身給你的東西,而不是你的超載。

// .h and in class 
friend std::ostream& operator<<(std::ostream& os, MyClass const& v); 

// .cpp 
std::ostream& operator<<(std::ostream& os, MyClass const& v){ 
    // print it 
} 
2

沒有這樣的限制;你可能只是寫錯了。應該是這樣的:

class Foo 
{ 
    int n; 

    friend std::ostream & operator<<(std::ostream &, Foo const &); 
}; 

std::ostream & operator<<(std::ostream & o, Foo const & x) 
{ 
    return o << x.n; 
} 
9

問題出在您定義它的方式。這不是班級的會員,它只是該班級的朋友。您需要刪除前綴Annuaire::。因此,改變這種:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ // ... 

這樣:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj){ // ... 

的原因錯誤信息是Annuaire::operator<<(std::ostream& os, const Annuaire& obj)期望三個參數:Annuaire情況下,它的要求(如this),並與兩個附加參數(osobj)。

3

朋友函數,即使他們似乎要在類中聲明不是成員函數,而是命名空間級函數(在封閉的名稱空間中)。在你的代碼正確聲明友元函數,但你試圖把它定義爲類的成員函數:

std::ostream& Annuaire::operator<<(std::ostream& os, const Annuaire& obj){ 

這一定義將是的Annuaire成員函數,稱爲operator<<,有兩個參數,這是無效的,因爲operator<<可以通過以下兩種方式之一重載:作爲一個帶有兩個參數(左側和右側)的自由函數,或者作爲出現在表達式的lhs中的類的成員函數, rhs類型。在這個特定的情況下,由於LHS是std::ostream,你不能修改它,你留下了使用免費的功能的唯一選擇:

std::ostream& operator<<(std::ostream& os, const Annuaire& obj) 
+0

+1用於在封閉名稱空間上添加註釋。在實際函數定義不夠之前添加'using namespace X'。 – moooeeeep

2

正如大衛的答覆中提到,在這種情況下,運營商是不是成員函數,它只是在同一個命名空間中的一個好友函數。這指出了我在解決一個非常類似的問題時正確的方向。

我發佈了這個答案,因爲它不是立即明顯的給我。也許是因爲我添加運算符的實現文件沒有完全包含在命名空間中,而是使用了using-directive。

不應該是相關的,但我使用VS2013。

//Foo.h 
namespace Bar{ 
    class Foo 
    { 
    public: 
     Foo(); 
    private: 
     int n; 
     friend std::ostream & operator<<(std::ostream &, Foo const &); 
    }; 
} 

//Foo.cpp 
using namespace Bar; //won't apply to the operator definition 
Foo::Foo(){}// doesn't require the Bar qualifier because of the using-directive 

//the operator required the Bar namespace qualifier 
std::ostream & Bar::operator<<(std::ostream & o, Foo const & x) 
{ 
    return o << x.n; 
} 
+0

準確地說我的問題!我不太確定爲什麼會發生這種情況。 – Flynsee