C++ 将模板申明为友元

代码编译运行环境:VS2017+Debug+Win32


严格来说,函数模板(类模板)是不能作为一个类的友元的,就像类模板之间不能发生继承关系一样。只有当函数模板(或类模板)被实例化之后生成模板函数(或模板类),该函数(或类)才能作为其他的类的友元。为了叙述的方便,我们也称一个函数模板(或类模板)是一个类或类模板的友元,其实真正的含义是函数模板(或类模板)被实例化后生成的模板函数(模板类)作为类(或模板类)的友元。

1.把函数模板声明为类模板的友元

将函数模板申明为类模板的友元有三种方式。

##1.1在类模板内部将函数模板声明为友元
考察如下代码:

#include <iostream>
using namespace std;

template<typename T> class A {
	T num;
public:
	A() {
		num=T(5.5);
	}
	template<typename T> friend void show(const A<T>&a);
};

template<typename T> void show(const A<T>&a) {
	cout<<a.num<<endl;
}

int main() {
	A<int> a;
	show<int>(a);
}

程序正确运行并输出5。

1.2 在类模板内部对显示模板参数的函数模板申明为友元

这种方法需要前置申明函数模板,考察如下程序。

#include <iostream>
using namespace std;
template<typename T>class A;
template<typename T>void show(const A<T>&a);

template<typename T>class A {
	T num;
public:
	A() {
		num=T(5.5);
	}
	friend void show<T>(const A<T>&a);
};

template<typename T> void show(const A<T>&a) {
	cout<<a.num<<endl;
}

int main() {
	A<int> a;
	show<int>(a);
}

程序正确运行并输出5。

1.3 在类模板内部直接声明并定义友元函数

这种情况只能在模板类内部一起把函数的定义写出来,不能在外部实现,因为外部需要类型参数,而需要类型参数就是模板了。其实这种情况相当于一般的模板类的成员函数,也相当于一个函数模板。考察如下代码。

#include <iostream>
using namespace std;

template<typename T>class A {
	T num;
public:
	A() {
		num=T(5.5);
	}
	friend void show(const A<T>&a) 
	{
		cout<<a.num<<endl;
	}
};

int main() {
	A<int> a;
	show(a);
	getchar();
}

程序正常编译运行并输出5。当然,将友元函数的定义改为:

template<typename T> void show(const A<T>&a)
{
	cout<<a.num<<endl;
}

也是完全可以的,如果将函数模板放在类模板外定义的话,和第一种方式相同。将函数模板申明为普通类的友元方式和上面相同,不再赘述。

2.把类模板声明为类模板的友元

把类模板声明为类模板的友元可以有两种方式。

2.1 在类模板内部将模板类申明为友元

这里要注意是对实例化后的模板类将其申明为类模板的友元,而不是类模板,因此实例化类模板时,类模板需要前置申明。考察如下程序。

#include <iostream>
using namespace std;

template<typename T>class B; //类模板前置申明

template<typename T> class A {
	T num;
public:
	A() {
		num=T(5.5);
	}
	friend class B<T>;
};

template<typename T> class B {
public:
	static void show(const A<T>& a) {
		cout<<"a.num:"<<a.num<<endl;	
	}
};

int main() {
	A<int> a;
	B<int>::show(a);
}

程序正常编译运行并输出:a.num:5。

2.2 在类模板内部将类模板申明为友元

这里要注意是直接将类模板申明为类模板的友元,而不是实例化后的模板咧,要与上面区别对待。这里就不需要将类模板B提前申明了,在类模板A中将B申明为:

template< class T> friend class B;

同样可以将类模板B申明为类模板A的友元。

不过,这两种方式在概念上还是有一些差异。第一种方式,类模板B的实例化依赖于类模板A的参数T。也就是说,对于一个特定的模板类A< t>来说,只有一个B的实例B< t>是它的友元类。而在第二中方式中,对于一个特定的模板类A< t>来说,B的任何实例B< u>都是它的友元类。

将类模板申明为普通类的友元方式和上面相同,不再赘述。


参考文献

[1] 怎样把函数模板声明为类模板的友元
[2] 陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008.P218-222

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值