2025年4月10日 星期四 乙巳(蛇)年 正月十一 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > VC/VC++

C++类模板与友元详解

时间:05-03来源:作者:点击数:414

下面我们分四种情况分别讨论。

1. 函数、类、类的成员函数作为类模板的友元

函数、类、类的成员函数都可以作为类模板的友元。程序示例如下:

  • void Func1() { }
  • class A { };
  • class B
  • {
  • public:
  • void Func() { }
  • };
  • template <class T>
  • class Tmpl
  • {
  • friend void Func1();
  • friend class A;
  • friend void B::Func();
  • };
  • int main()
  • {
  • Tmpl<int> i;
  • Tmpl<double> f;
  • return 0;
  • }

类模板实例化时,除了类型参数被替换外,其他所有内容都原样保留,因此任何从 Tmp1 实例化得到的类都包含上面三条友元声明,因而也都会把 Func1、类 A 和 B::Func 当作友元。

2. 函数模板作为类模板的友元

例题:在《C++类模板(模板类)》一节中我们定义了 Pair 模板,将<<运算符重载为一个函数模板,并将该函数模板作为 Pair 模板的友元,这样,任何从 Pair 模板实例化得到的对象都能用<<运算符通过 cout 输出。

程序代码如下(函数模板作为类模板的友元):

  • #include <iostream>
  • #include <string>
  • using namespace std;
  • template <class T1, class T2>
  • class Pair
  • {
  • private:
  • T1 key; //关键字
  • T2 value; //值
  • public:
  • Pair(T1 k, T2 v) : key(k), value(v) { };
  • bool operator < (const Pair<T1, T2> & p) const;
  • template <class T3, class T4>
  • friend ostream & operator << (ostream & o, const Pair<T3, T4> & p);
  • };
  • template <class T1, class T2>
  • bool Pair <T1, T2>::operator< (const Pair<T1, T2> & p) const
  • { //“小”的意思就是关键字小
  • return key < p.key;
  • }
  • template <class Tl, class T2>
  • ostream & operator << (ostream & o, const Pair<T1, T2> & p)
  • {
  • o << "(" << p.key << "," << p.value << ")";
  • return o;
  • }
  • int main()
  • {
  • Pair<string, int> student("Tom", 29);
  • Pair<int, double> obj(12, 3.14);
  • cout << student << " " << obj;
  • return 0;
  • }

程序的输出结果是:(Torn, 29) (12, 3.14)

第 13、14 行将函数模板 operator<< 声明为类模板 Pair 的友元。在 Visual Studio 中,这两行也可以用下面的写法替代:

friend ostream & operator<< <T1, T2>(ostream & o, const Pair<T1, T2> & p);

但在 Dev C ++ 中,替代后编译就无法通过了。

编译本程序时,编译器自动生成了两个 operator << 函数,它们的原型分别是:

ostream & operator << (ostream & o, const Pair<string, int> & p);
ostream & operator << (ostream & o, const Pair<int, double> & p);

前者是 Pair <string, int> 类的友元,但不是 Pair<int, double> 类的友元;后者是 Pair<int, double> 类的友元,但不是 Pair<string, int> 类的友元。

3. 函数模板作为类的友元

实际上,类也可以将函数模板声明为友元。程序示例如下:

  • #include <iostream>
  • using namespace std;
  • class A
  • {
  • int v;
  • public:
  • A(int n) :v(n) { }
  • template <class T>
  • friend void Print(const T & p);
  • };
  • template <class T>
  • void Print(const T & p)
  • {
  • cout << p.v;
  • }
  • int main()
  • {
  • A a(4);
  • Print(a);
  • return 0;
  • }

程序的输出结果是:4

编译器编译到第 19 行Print(a);时,就从 Print 模板实例化出一个 Print 函数,原型如下:

void Print(const A & p);

这个函数本来不能访问 p 的私有成员。但是编译器发现,如果将类 A 的友元声明中的 T 换成 A,就能起到将该 Print 函数声明为友元的作用,因此编译器就认为该 Print 函数是类 A 的友元。

思考题:类还可以将类模板或类模板的成员函数声明为友元。自行研究这两种情况该怎么写。

4. 类模板作为类模板的友元

一个类模板还可以将另一个类模板声明为友元。程序示例如下:

  • #include <iostream>
  • using namespace std;
  • template<class T>
  • class A
  • {
  • public:
  • void Func(const T & p)
  • {
  • cout << p.v;
  • }
  • };
  • template <class T>
  • class B
  • {
  • private:
  • T v;
  • public:
  • B(T n) : v(n) { }
  • template <class T2>
  • friend class A; //把类模板A声明为友元
  • };
  • int main()
  • {
  • B<int> b(5);
  • A< B<int> > a; //用B<int>替换A模板中的 T
  • a.Func(b);
  • return 0;
  • }

程序的输出结果是:5

在本程序中,A< B<int> > 类成为 B<int> 类的友元。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门