在学习c++类时我们学习了——友元。现在简单复习一下c++中的友元。首先我们要清楚友元的概念:某个类或者函数访问友元声明所在的类。也就时说在某个类中声明一个友元函数或者友元函数具有访问这个类的权限。然而,由于以下两个事实,这些简单的概念却变得复杂:
- 友元声明可能是某个实体的唯一声明。
- 友元函数的声明可以是一个定义。
- 友元类的声明不能是类定义。
-
class Stack_; class Stack { friend void function1(int) { std::cout << "Jay"; } friend Stack_; };
友元函数:
-
template<typename T,typename U> void function(T, U) {}; class Stack { friend void function<>(int, int);// 可以进行实参演绎 friend void function<int, int>(int, int); friend void fuction<int&, int>(int, int); //实参演绎错误 friend void fuction<>(int, int) {}; //error };
为什么最后一个是错误的呢?因为在类中友元声明不能定义一个模板的实例化。但是有两种情况确实合法,想在就让我们看看。
-
如果名称不是受限的(也就是说,没有包含一个形如双冒号的域运算符),那么该名称一定不是引用一个模板实列。
- 如果名称是受限的(也就是说,前面有双冒号的域运算符),那么该名称必须引用一个在此之前声明的函数或者函数模板。
在前面的例子中我们是在普通的类中声明友元函数或者友元类,也可以在类模板中声明友元函数,所以我们就可以使用类模板的模板参数来标识友元函数。
template<typename T,typename U>
void function(T, U);
template<typename T,typename U>
void function1(T, U);
template<typename T,typename U>
class Stack {
friend void function<T, U>(T, U) {}; //竟然可以定义
friend void function<T, U>(T, U);
};
- 然而,有时候我们需要将模板的所有实列成友元,这时就需要声明模板友元模板。
-
template<typename T,typename U> class Stack_; template<typename T,typename U> class Stack { template<typename T,typename U> friend class Stack_; };
友元模板声明的只是基本模板(函数模板)和基本模板的成员。当进行这些声明之后,与该模板相对应的模板偏特化,全特化和显示特化都会被自动的看成友元。