C++的探索路18泛型程序设计与模板之细节

Posted Guerrouj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++的探索路18泛型程序设计与模板之细节相关的知识,希望对你有一定的参考价值。

本部分将对类模板的技术细节进行陈述,如类模板的非类型参数,类模板与继承,类模板与友元,类模板中的静态成员;及如何在多文件中使用模板。该部分和前面基础部分内容区别不大,给一些基本例子。

类模板中的非类型参数

我们定义类模板的时候,一般在类前面加上template<class T,....>语句,但这不意味着只能将类作为参数,参数表中还能出现非类型参数。比如可以定义长度需要定义,类型需要定义的类模板:

template<class T,int size>
class CArray 
	T array[size];
public:
	CArray()
		for (int i = 0; i < size; ++i) 
			array[i] = 0;
		
	
	void Print() 
		for (int i = 0; i < size; ++i)
			cout << array[i] << endl;
	
;
int main() 
	CArray<int, 40>a;
	a.Print();
	return 0;

在类定义部分该程序,定义了类型为T,长度为size的array数组;内部包含Print()成员函数及无参构造函数对CArray()进行初始化。主函数的内部则在CArray的基础上定义了定义了一个包含长度为40的整形成员的CArray数组对象。

注意CArray<int,40>与CArray<int,50>是两个不同的,这两个类的对象之间无法进行赋值。

类模板与继承

这一段,,,,可能有点绕。。。涉及的四个内容为:类模板从类模板派生、类模板从模板类派生、类模板从普通类派生以及普通类从模板类派生。

但万变不离其宗的是,我们要把经过类型实例化的模板看成一个类。千万别用成对象

类模板从类模板派生

这个相对简单理解点,就把类模板看成一个类

template<class T1,class T2>
class A 
	T1 v1; T2 v2;
;
template<class T1, class T2>
class B:public A<T2,T1> 
	T1 v3; T2 v4;
;
template<class T>
class C :public B<T, T> 
	T v5;
;
int main() 
	B<int, double>obj1;
	C<int>obj2;
	return 0;

类模板从模板类派生

template<class T1, class T2>
class A 
	T1 v1; T2 v2;
;
template<class T1, class T2>
class B :public A<double,int> 
	T1 v3; T2 v4;
;
template<class T>
class C :public B<T, T> 
	T v5;
;
int main() 
	B<int, double>obj1;
	C<int>obj2;
	return 0;

类模板从普通类派生及普通类从模板类派生也并没有什么新颖的知识点,在这跳过。


类模板和友元

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

程序如下:

void Func1()
class A;
class B 
public:
	void Func()
;
template<class T>
class Tmp1 
	friend void Func1();
	friend void B::Func();
	friend class A;
;
int main() 
	return 0;

注意,类的成员函数写的时候一定要注意写域作用符。

同理函数模板作为类模板的友元等等与基本的友元部分区别不大,跳过。

类模板中的静态成员

类模板中定义静态成员,从该类模板实例化得到的所有类,都包含同样的静态成员,看一个有点怪异的程序,程序示例如下:

template<class T>
class A 
private:
	static int count;
public:
	A() 
		count++;
	
	~A() 
		count--;
	
	A(A&) 
		count++;
	
	static void PrintCount() 
		cout << count << endl;
	
;
template<>int A<int>::count = 0;
template<>int A<double>::count = 0;
int main() 
	A<int>ia;
	A<double>da;
	ia.PrintCount();
	da.PrintCount();

程序中定义了一个模板类A,模板类A中包含静态私有变量count,调用两种类型的构造函数的时候均执行count++,调用析构函数的时候执行count--。

静态成员变量需要首先进行类外声明,声明在类外的方式可以为我们熟悉的template<T> int A<T>::count=0,也可以写为上面的template<>int A<T>::count的形式.

所以下次我们见到template<>intA<T>的形式就是进行类型声明。


========

前面还提到本部分将介绍在多个文件中使用模板,However,这和普通函数定义在头文件内部没有什么区别;所以跳过。



总结

1,类模板的参数表除了可以定义类外还可以填入非类型参数,比如int size等内容。但注意,不同的非类型参数代表了不同的类,比如A<int,40>≠A<int,50>;所以不能进行相互赋值。

2,类模板与继承和友元这两部分与前面面向对象的内容差别不大,基本忽略不计。

3,类模板中的静态成员如静态成员的基本要求:需要在类外进行初始化声明。声明形式可以为传统形式

template<T>

T1 A<T>::func=0;

T1为func静态变量在类内的类型,A为包含func()函数的类。

也可以为template<>T1 A<T>::func=0;

写法不同,依据个人喜好进行改变。









以上是关于C++的探索路18泛型程序设计与模板之细节的主要内容,如果未能解决你的问题,请参考以下文章

C++的探索路17泛型程序设计与模板之基本形式

C++的探索路19泛型程序设计与模板之练习题

C++的探索路19泛型程序设计与模板之练习题

C++的探索路20标准模板库STL之STL的基本概念与容器

C++的探索路20标准模板库STL之STL的基本概念与容器

C++的探索路15多态与虚函数之高级篇