栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++类模板

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++类模板

类模板
//模板不是函数,不能单独编译,所以要将模板信息放在同一个头文件中
template
class Stack
{
private:
    enum{MAX=10};
    T items[MAX];
    int top;
public:
    Stack();
    bool isempty();
    Stack(const Stack& st);
    Stack& operator=(const Stack& st);
};
template
Stack::Stack(){top=0;}

template
bool Stack::isempty(){return top==0;}

template
Stack::Stack(const Stack& st){} //参数中也可以使用Stack

template
Stack& Stack::operator=(const Stack & st){} //参数中也可以使用Stack
//原型中返回类型是引用,但是在定义是需要定义为Stack
//原型是缩写形式,只能应用在类中
//即指定返回类型或者使用作用域解析符时,必须使用Stack
使用模板类
Stack a;
Stack b;
//类模板必须显式提供所需的类型
非类型参数
template //n为非类型参数或者表达式参数
class ArrayTp
{
private:
	T ar[n]; //未使用new,使用的是栈
public:
	ArrayTp() {};
	explicit ArrayTp(const T& v);
	T& operator[](int i);
};

template
ArrayTp::ArrayTp(const T& V)
{
	for (int i = 0; i < n; i++)
	{
		ar[i] = n;
	}
}

template
T& ArrayTp::operator[](int i)
{
	return ar[i];
}
  1. 非类型参数可以是整形、枚举、引用或者指针。

template是不合法的,可以是template

  1. 模板代码不能修改非类型参数的值,也不能使用参数的地址。所以不能使用n++或者&n之类的,
  2. 实例化模板时,非类型参数的值必须是常量表达式
  3. 每种数组大小都会生成自己的模板
//这会生成两个独立的类声明
ArrayTp v1;
ArrayTp v2;

使用非类型参数的优缺点:

**优点:**可以直接使用数组声明即内存栈来维护数组,执行速度偏快

**缺点:**构造函数法(不使用非类型参数)更通用,因为数组大小是存储在定义中,而不是硬编码,这样可以将不同尺寸的数组进行相互赋值,且也可以动态改变数组的大小

模板多功能性

可以将常规类的技术用于模板类,如模板类可作为基类、作为类型参数等。

template
class Array
{
private:
    T entry;
};

template
class GrowArray::public Array
{};

template
class Stack
{
    Array ar;
};

Array> a;//c++11之前,最后两个符号必须隔开
  1. 递归使用模板

ArrayTp< ArrayTp,10> twoTp≈int twoTp[10][5]

  1. 使用多个类型参数
template
class Pair
{
private:
	T1 a;
	T2 b;
	...
};
  1. 默认类型模板参数
template
class Topp{};

*注意:*可以为类模板类型参数提供默认值,不能为函数模板参数提供默认值。但是函数模板和类模板都可以为非类型参数提供默认值

模板的具体化
  1. 隐式实例化
//编译器在需要对象之前不会生成类的隐式实例化
ArrayTp * pt;//声明一个pointer,目前还不需要对象
pt = newArray;//隐式实例化
  1. 显示实例化
//使用template来声明显示实例化
template class ArrayTp;//将ArrayTp生命为一个类
//该声明必须位于模板定义所在的名称空间中
  1. 显示具体化
template<> class ArrayTp{...};

ArrayTp<> a;//使用泛型模板
ArrayTp b;//使用具体化模板
  1. 部分具体化
template class Pair{};
//template后面的<>中是未被具体化的类型参数 如果该<>中为空,则是3.显示具体化

//如果有多个模板可供选择,编译器使用具体化程度最高的模板
Pair p1;//使用Pair
Pair p2;//使用Pair
Pair p3;//使用Pair

为指针提供特殊版本来实现部分具体化

template
class Feeb{...}

template
class Feeb{...}

Feeb fb1;//使用通用模板 T为char
Feeb fb2;//使用T*,T为char

部门具体化可实现各种限制

//通用模板
template class Trio{};
//T2与T3相同
template class Trio{};
//T2、T3是T1的指针类型
template class Trio{};

Trio t1;//通用模板
Trio t2;//Trio
Trio t3;//Trio
成员模板
template
class A
{
private:
	template
	class B{}; //嵌入类
	B q;
public:
	A(T t, int i) {};
	template
	U fun(U u, T t) {return u;}
};

A a(3.5, 3); 
a.fun(10, 2.3);//自动推断,U为int
//有些编译器是不能在模板中声明B类和fun方法,在外面定义,而有些可以,如果可以需要这样定义:
template
class A
{
private:
	template
	class B;
	B q;
public:
	A(T t, int i) {};
	template
	U fun(U u, T t);
};

template
	template
	class A::B {};

template
	template
	U A::fun(U u, T t) { return u; }

//由于T、V、U是嵌套关系,所以需要这样定义:
template
	template
//而不能这样:
template  
//另外还需要使用作用域限定符来指出B与fun是A的成员
模板作为参数

template