类模板友元函数的实现(综述)(入门)

为什么要使用模板(函数模板、类模板)

程序设计中,会遇到这样的问题:程序实体所要完成的功能完全一样,但是它们所操作的数据类型却不一样。对于这些函数或者类,采用一个函数和一个类来进行描述的话,将会大大简化程序设计的工作。

比如求最大值max()的实现:有int、int ; double、double ; float、float……需要定义多个函数。但是这些函数的实现,除了数据类型不同,其他都相同。使用函数模板可以简化程序。

template         //也可以使用template
T max(T a, T b)
{
	if (a > b)
		return a;
	else
		return b;
}

有了函数模板,那么在使用类的时候,成员函数、友元函数如何使用函数模板呢?这就需要类模板。

//表示矩阵,可以自定义行列数,值可以是不同数据类型
template
class matrix {
	C(*p)[N];
public:
	matrix();
        ~matrix();
};

template

声明一系列泛型,仅作用与之后的一个函数,在不同函数中,与名称T无关,代表不同的含义。

除了声明类型,还可以声明数值

template

typename

基本上可以与class互换。因为使用class易混淆,故引入typename。

与class不同的是,typename可以告诉编译器其后是类型名。常在嵌套依赖类型(nested depended name)中使用,简化表达。

//嵌套依赖类型
template
class text1
{
public:
	typedef int MYINT;  //必须共有,否则无法访问
private:
	MYINT a;
};

template
class test2
{
	typedef typename TP2::MYINT MY_INT;
	MY_INT b;
};

//调用语句
test2> n;

类模板

定义类模板可以在成员友元函数中使用泛型,简化程序。同函数模板使用基本相同。不同的是,在类的使用时,定义对象(实例化)的时候需要显示写出泛型。如上例

//调用语句
test2> n;

类模板在成员函数、友元函数中的使用

成员函数

体内实现时和普通类一样

体外实现时声明同普通类一样,定义时要加上泛型声明。

友元函数

体内实现时要加上泛型声明(一处)。

体外实现时声明和定义时都要加上泛型声明(两处)。

但是体外实现可移植性较差,vs可使用,gcc系列编译器和linux都不支持这种写法。故友元函数最好写成体内实现形式。

而友元函数不能体外实现的原因也很简单。上文提到template泛型声明仅作用于一个函数,与typename泛型名相同与否无关。故友元函数体外实现时,编译器看来就是另一个使用模板的函数,与类声明的泛型无关。在调用函数的时候,该函数无法知道如同定义时显示写出的泛型。而友元声明本身只是允许访问私有成员。故无法体外实现。vs对其进行了特殊处理。

举例:

template
class matrix {
	C(*p)[N];

public:
//成员函数 构造析构
  //体内实现
	matrix();
{
	p = new C[M][N];
}
  //体外实现 声明
	~matrix();

//友元函数 体内实现
	friend istream& operator>>(istream& in, matrix& s)
	{
		for (int i = 0; i < M; i++)
			for (int j = 0; j < N; j++)
				in >> s.p[i][j];
		return in;
	}

};
//成员 体外 定义
template
matrix::~matrix()
{
	delete[]p;
}


//调用
int main()
{
	const int m = 2, n = 3;  //必须const
	matrix matri;   //调用构造
	cin >> matri;            //调用重载运算符
	//调用析构
	return 0;
}

 

你可能感兴趣的:(类模板友元函数的实现(综述)(入门))