让某个类B成为另一个类A的友元类,这样的话类B就可以在其成员函数中访问A的所有成员,而不管这些成员在类A在中是用什么(public,protected, private)修饰符修饰的。
#include
// 类模板B的声明
template <typename D>
class B;
template <typename T>
class A {
friend class B<long>; // 类模板B的实例B 成为A的友元类
private:
int data;
};
template <typename D>
class B {
public:
void callBAF()
{
A<int> a_obj;
a_obj.data = 5;
std::cout << a_obj.data << std::endl;
}
};
int main(int argc, char** argv)
{
B<long> b_obj;
b_obj.callBAF();
return 0;
}
#include
template <typename T>
class A {
template <typename D>
friend class B; // 类模板B成为A的友元类
private:
int data;
};
template <typename D>
class B {
public:
void callBAF()
{
A<int> a_obj;
a_obj.data = 5;
std::cout << a_obj.data << std::endl;
}
};
int main(int argc, char** argv)
{
B<int> b_obj;
b_obj.callBAF();
return 0;
}
如果传递进来的类型模板参数是一个类类型,则这个类类型可以成为当前类模板的友元类.如果传递给类型模板参数不是一个类类型,那么就被忽略
#include
template <typename T>
class A {
friend T; // 如果传入不是类类型,这行代码将会被忽略
private:
int data;
};
class B {
public:
void callA()
{
A<B> a_obj; // 让B成为A类的友元类
a_obj.data = 12;
std::cout << a_obj.data << std::endl;
}
};
int main(int argc, char** argv)
{
B b_obj;
b_obj.callA();
// A a_obj; 因为B类并不是A的友元类,因此不能访问私有成员变 量
// a_obj.data = 12;
return 0;
}
#include
// 函数模板func的声明
template <typename U, typename V>
void func(U val1, V val2);
template<typename T>
class Men {
friend void func<int, int>(int, int); // 是两个模板实参
friend void func<float, int>(float, int);
friend void func<int, float>(int, float);
private:
void func_man() const
{
std::cout << "Men::func_man called" << std::endl;
}
};
template <typename U, typename V>
void func(U val1, V val2)
{
std::cout << "val1:" << val1 << " val2:" << val2 << std::endl;
Men<int> men;
men.func_man();
}
int main(int argc, char** argv)
{
// 函数模板调用方式
func(2, 3); // 实例化void func(int, int){...}
func<float>(4.6f, 5); // 第一个模板参数指定,第二个模板参数编译器推断
func<int, float>(4, 5.6f);
return 0;
}
将函数模板(泛化版本)声明为类模板的友元模板之后,那么函数模板的特化版本也会成为类模板的友元
#include
template <typename T>
class Men {
// 函数模板成为类模板的友元函数模板
template <typename U, typename V>
friend void func(U, V);
private:
void func_man() const
{
std::cout << "Men::func_man called" << std::endl;
}
};
// func 泛化版本
template <typename U, typename V>
void func(U val1, V val2)
{
std::cout << "泛化版本:"
<< "val1:" << val1 << " val2:" << val2 << std::endl;
Men<int> men;
men.func_man();
}
// func 全特化版本
template <>
void func(double val1, double val2)
{
std::cout << "全特化版本:"
<< "val1:" << val1 << " val2:" << val2 << std::endl;
Men<int> men;
men.func_man();
}
int main(int argc, char** argv)
{
// func(2, 3);
// func(4.6f, 5);
// func(4, 5.6f);
// func(4.8, 5.6);
return 0;
}
这种友元函数能够被调用,而且只有在代码中调用了函数的时候,编译器才会实例化出这个函数,之所以这样定义友元函数,一般是因为在该友元函数中会用到这个类模板。这种友元函数的调用与普通函数一样。
#include
template <typename T>
class Men {
friend void func(Men<T>& men)
{
men.func_man();
};
private:
void func_man() const
{
std::cout << "Men::func_man called" << std::endl;
}
};
int main(int argc, char** argv)
{
Men<double> man; // 虽然func在Men类模板中,还未调用,因此func还未实例化
func(man); // 直接调用Men类模板中定义的友元函数func
return 0;
}