我写了下面的代码:
#include <iostream>
using namespace std;
template <class T>
class AA
{
T a;
public:
AA()
{
a = 7;
}
friend void print(const AA<T> & z);
};
template <class T>
void print(const AA<T> & z)
{
cout<<"Print: "<<z.a<<endl;
}
void main()
{
AA<int> a;
print<int>(a);
}
出现以下错误:
error C2248: 'AA<T>::a' : cannot access private member declared in class 'AA<T>'
1> with
1> [
1> T=int
1> ]
1> c:\users\narek\documents\visual studio 2008\projects\aaa\aaa\a.cpp(7) : see declaration of 'AA<T>::a'
1> with
1> [
1> T=int
1> ]
1> c:\users\narek\documents\visual studio 2008\projects\aaa\aaa\a.cpp(30) : see reference to function template instantiation 'void print<int>(const AA<T> &)' being compiled
1> with
1> [
1> T=int
1> ]
怎么了?
附言我正在使用 Visual Studio 2008。
最佳答案
问题是当你做类似的事情时
template<class T>
class AA {friend void print(const AA<T>&);};
然后你实例化AA
像这样
AA<int> a;
友元声明将被实例化为
friend void print(const AA<int>&);
这是一个非模板函数!这意味着编译器不会将友元声明与您的 print
匹配。功能。
解决方案基本上是声明print
之前AA
并明确告诉编译器您的友元声明是在谈论模板函数。像这样:
#include <iostream>
using namespace std;
//forward declare AA because print needs it
template<class T>
class AA;
//declare print before AA to make the friend declaration
//match with this function
template<class T>
void print(const AA<T> & z);
template <class T>
class AA
{
//the <> is needed to make sure the compiler knows we're
//dealing with a template function here
friend void print<>(const AA<T> & z);
public:
AA() {a = 7;}
private:
T a;
};
//implement print
template<class T>
void print(const AA<T> & z)
{
cout<<"Print: "<<z.a<<endl;
}
int main()
{
AA<int> a;
print(a);
}
如果不添加 <>
,看看会发生什么很有趣在好友声明中。您将收到链接器错误。为什么?好吧,因为编译器无法将 friend 声明与您的模板匹配 print
函数,它将隐式地假设一个具有原型(prototype)的函数
void print(const AA<int>&);
存在。因为我没有为调用 print
明确提供模板参数(这不是必需的,因为编译器应该能够推断出这一点),编译器会将此调用与声明为友元的函数相匹配。此函数未在任何地方实现,因此出现链接器错误。
关于c++ - 如何为具有相同模板的模板类定义和使用友元函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3043214/