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)