【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;

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









  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值