我有以下模板类和模板函数,它们打算访问该类'私人数据成员:
Data
要将这两个函数声明为#include <iostream>
template<class T>
class MyVar
{
int x;
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
的朋友函数,我已在MyVar<T>
的声明中尝试了以下方式来声明友谊。它们都不起作用。我该怎么办?
template<class T> class MyVar
答案 0 :(得分:4)
最简单的选择是在班级中定义朋友:
template<class T>
class MyVar
{
int x;
friend void printVar(const MyVar & var) {
std::cout << var.x << std::endl;
}
friend void scanVar(MyVar & var) {
std::cin >> var.x;
}
};
缺点是函数只能通过依赖于参数的查找来调用。在您的示例中,这不是问题,但如果他们没有合适的参数,或者您希望在不调用它的情况下指定名称,则可能会出现问题。
如果你想要一个单独的定义,那么模板必须在类定义之前声明(因此它可用于朋友声明),但之后定义(因此它可以访问类成员)。该类也必须在函数之前声明。这有点乱,所以我只展示两个功能中的一个:
template <typename T> class MyVar;
template <typename T> void printVar(const MyVar<T> & var);
template<class T>
class MyVar
{
int x;
friend void printVar<T>(const MyVar<T> & var);
};
template <typename T> void printVar(const MyVar<T> & var) {
std::cout << var.x << std::endl;
}
答案 1 :(得分:2)
我成功完成了以下工作
#include <iostream>
template<class T>
class MyVar;
template<class T>
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);
template<class T>
class MyVar
{
int x;
friend void printVar<T>(const MyVar<T>& var);
friend void scanVar<T>(MyVar<T>& var);
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
UPD :http://en.cppreference.com/w/cpp/language/friend在&#34;模板朋友运营商&#34;
下与运营商谈论类似案例模板朋友的常见用例是非成员的声明 作用于类模板的运算符重载,例如
operator<<(std::ostream&, const Foo<T>&)
用于某些用户定义的Foo<T>
这样的运算符可以在类体中定义,具有效果 为每个
的朋友operator<<
生成单独的非模板T
使非模板operator<<
成为其Foo<T>
...
或函数模板必须在之前声明为模板 类主体,在这种情况下
的完整专业化Foo<T>
中的朋友声明可以 请参阅operator<<
T
答案 2 :(得分:1)
这个编译在MSVC2013上。基本上在朋友
之前将前向声明添加到类和函数中template<class T> class MyVar ; // class forward declaration
template<class T> ; // function forward declarations
void printVar(const MyVar<T>& var);
template<class T>
void scanVar(MyVar<T>& var);
template<class T>
class MyVar
{
friend void printVar<T>(const MyVar<T>&);
friend void scanVar<T>(MyVar<T>&);
int x;
};
template<class T>
void printVar(const MyVar<T>& var)
{
std::cout << var.x << std::endl;
}
template<class T>
void scanVar(MyVar<T>& var)
{
std::cin >> var.x;
}
struct Foo {};
int main1(void)
{
MyVar<Foo> a;
scanVar(a);
printVar(a);
return 0;
}
答案 3 :(得分:1)
有一种解决方案,既简单又涉及到将好友函数的声明与定义分开。在Friend函数的声明中(在类内部),您必须提供与该类接受的模板不同的模板参数(这是有道理的,因为该函数不是该类的成员)。
template<class T>
class MyVar
{
int x;
template<typename Type>
friend void printVar(const MyVar<Type> & var);
template<typename Type>
friend void scanVar(MyVar<Type> & var);
};
template<typename T>
void printVar(const MyVar<T> & var) {
}
template<typename T>
void scanVar(MyVar<T> & var) {
}
不需要前向声明,并且声明和定义是分开的。