3
#include <iostream> 
using namespace std; 
template <typename T> 
class test 
{ 
    T y; 

public: 
    test(T k) : y(k) {} 
    friend int a(T& x); 
}; 

template <typename T> 
int a(T& x) 
{ 
    cout << x.y; 
    return 9; 
} 

template <> 
class test<int> 
{ 
    int y; 
public: 
    test(int k) : y(k) {} 
    friend int a(int& x); 
}; 

template <> 
int a<int>(int& x) 
{ 
    cout << "4"; 
    return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    test<int> z(3); 
    a(z); 

    return 0; 
} 

我想交個朋友類測試類的(在真實情況下,這是一個運營商的ofstream的< <)。但我不知道如何定義專業類的模板好友功能。朋友專門的模板類(C++)

此外,上面的代碼顯示了這個編譯錯誤信息;

錯誤C2248: '測試:: Y':不能訪問私有成員在 類 '測試'

問題補充申報;

亞倫麥克戴德適合我,但我試圖超載運營商< < ofstream class。

friend ofstream& operator<< <test<int>> (ofstream& os, const test<int>& t); 

我添加到以上測試類和

template<> 
ofstream& operator<< <test<int> > (ofstream& os, const test<int>& t) 
{ 
    os << t.y; 
    return os; 
} 

使用上面的代碼的代碼。但它看起來像我不能使用操作系統< < t.y(這是INT)我不明白爲什麼會發生這種情況。該錯誤消息是

錯誤C2027:使用未定義的類型 '的std :: basic_ofstream < _Elem,_Traits>'

回答

2

更新:這裏有http://ideone.com/3KGU4經過全面測試的版本爲其他問題,見http://ideone.com/w0dLo。)

有普通重載函數和模板函數之間的差異。例如,沒有任何參考模板的開發人員可以聲明:

void f(int x); 
void f(char *x); 

另外,開發人員可以使用模板,

template <class T> void f(T x); 

它們之間的主要區別是,與普通的功能,你必須決定一組固定的允許參數,並且您必須爲每個參數提供一個實現。使用模板,您可以更靈活。

在程序的後面,顯然你想a是一個模板函數,而不是簡單的(重載)普通函數。但是當編譯器第一次看到提到a(在第10行左右)時,它看起來像是在聲明一個普通的函數。要解決這個問題,你必須採取兩個步驟。你必須儘快即a是一個模板函數聲明,所以你的第一行應該是:

template <typename T> int a(T& x); 

然後,你必須聲明相關的友誼。如果Tint,則a取參數test<int>&而不是int&

friend int a<test<T> >(test<T> & x); // around line 10 
friend int a<test<int> >(test<int> & x); // around line 27 

a專業化應該是::所以這兩個朋友行應改爲

template <> 
int a< test<int> >(test<int>&) // around line 30 

額外的問題

使用ostream,而不是ofstream(或者包括#include <fstream>如果只輸出到文件而不輸出到cout)。在我的回答中,operator <<不是模板,而是一個正常的重載函數。我不確定是否有可能將operator<<作爲模板。另外,我將操作員定義在聲明和聲明爲朋友的地方。說實話,我認爲還有其他的,也許更好的方式,但是這對我有效。 。

4

這位朋友是不是一個模板,而是一個普通的功能:

friend int a(T& x); 

爲了有一個模板,它亦是朋友,請嘗試:

template<class U> 
friend int a(U& x); 

在評論中討論之後,也許我應該給我打算這些聲明的test類及其專業化:

template <typename T> 
class test 
{ 
    T y; 

public: 
    test(T k) : y(k) {} 

    template<class U> 
    friend int a(U& x); 
}; 

template <> 
class test<int> 
{ 
    int y; 
public: 
    test(int k) : y(k) {} 

    template<class U> 
    friend int a(U& x); 
}; 

輕微的缺點是,這使得所有的所有的a功能的朋友test類,但這通常不是一個大問題。

+2

或'朋友詮釋一個<>(INT & x);` – Xeo 2011-12-16 11:54:37

+0

@Xeo,這是不正確的參數是'測試``不int` – 2011-12-16 12:34:15

+0

@Aaron:對,我沒注意到。然而,Bo的回答也是錯誤的,因爲如果`test`被實例化爲兩種不同的類型,它會產生ODR違規。 – Xeo 2011-12-16 12:38:16

0

試試這個,和it works

#include <iostream> 
using namespace std; 

template <typename T> 
class test; 

template <typename T> 
int a(test<T>& x); 

template <typename T> 
class test 
{ 
    T y; 

public: 
    test(T k) : y(k) {} 
    friend int a<T>(test<T>& x); 
}; 

template <typename T> 
int a(test<T>& x) 
{ 
    cout << x.y; 
    return 9; 
} 

template <> 
class test<int> 
{ 
    int y; 
public: 
    test(int k) : y(k) {} 

    friend int a<int>(test<int> & x); 
}; 

template <> 
int a<int>(test<int> & x) 
{ 
    cout << "4"; 
    return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    test<int> z(3); 
    a(z); 

    return 0; 
} 

的問題是,模板函數a需要test模板類的參數。如果你想兩者具有相同的模板參數,然後,IMO你需要明確指出

template <typename T> 
    int a(test<T>& x); 

也爲inttemplate<> int a(int& x))的功能a專業化是沒有用在這裏。你需要有

template <> int a<int>(test<int> & x)