类模版

类模板是用来生成类的蓝图的,类模版是类的抽象,类模版实例化以后,就变为类,类就可以生成对象,动态数组vector就是类模版实例化的表现 vector<int> vi(100)。与函数模板不同之处是,编译器不能为类模板推断模板参数类型(函数模板可以通过参数来推断,而类模板没有),为了使用类模板,我们必须在模板后的<>中提供额外信息(显式模板实参列表)用来代替模板参数的模板实参列表,类模板的名字不是一个类型名,类模板用来实例化类型,而一个实例化的类型总是包含模板参数的。

类模板的成员函数

       与其他任何类相同,我们既可以在类模板内部,也可以在类模板外部为其定义成员函数,且定义在类模板内的成员函数被隐式声明为内联函数
       类模板的成员函数本身是一个普通函数,但是类模板的每个实例都有其自己版本的成员函数。因此,类模板的成员函数具有和模板相同的模板参数。所以定义在类模板之外的成员函数就必须以关键字template开始,后接类模板参数列表。
       默认情况下,对于一个实例化了的类模板,其成员只有在使用时才被实例化

在类内外对类模板名的使用

在类代码内简化模板类名的使用,当我们使用一个类模板类型时必须提供模板实参,但这一规则有一个例外,在类模板自己的作用域中,我们可以直接使用模板名而不提供实参。当我们在类模板外定义其成员时,必须记住,我们并不在类的作用域中,直到遇到类名才表示进入类的作用域。

template<typename T>
class BlobPtr
{
public:
	//当我们处于一个类模板的作用域中时,编译器处理模板自身引用时
	//就好像我们已经提供了与模板参数匹配的实参一样
	BlobPtr & operator++();  //与 BlobPtr<T>& operator++();一样
	BlobPtr & operator--();  //与 BlobPtr<T>& operator--();一样
};

//由于返回类型位于类的作用域之外,我们必须指出返回类型是一个实例化的BlobPtr
template<typename T>
BlobPtr<T>& BlobPtr<T>::operator++()
{
	//函数体内已经进入类的作用域,因此在定义ret时无须重复模板实参
	BlobPtr ret = *this;  //等价于BlobPtr<T> ret = *this;
	++*this;
	return ret;
}
#include "stdafx.h"
#include <iostream>
using namespace std;

#if 0

如果想模板化,可以 push 和 pop 不同的数据类型。主要由几个因素需要把控。
栈中的空间元素类型,压入元素类型,弹出元素类型,三者保持一致即可
#endif

template<typename T>
class Stack
{
public:
	Stack(int size=512)
	{
		space = new T[size];
		top = 0;
		_size = size;
	}

	~Stack(){}

	void push(T ch);
	T pop();
	bool isEmpty();
	bool isFull();

private:
	T* space;
	int top;
	int _size;
};

//在类外实现需要放上类模版template<typename T>,使其成为类模版的成员函数
//如果不放的话 系统默认是 类成员函数 而我们有的只是类模版
//而且 域作用符::前也要声明为类模版的成员 所以要变为Stack<T> 区别类成员
template<typename T>
void Stack<T>::push(T ch)
{
	if (!isFull())
	{
		space[top] = ch;
		top++;
	}
}

template<typename T>
T Stack<T>::pop()
{
	if (!isEmpty())
	{
		top--;
		return space[top];
	}
}

template<typename T>
bool Stack<T>::isEmpty()
{
	if (top == 0)
		return true;
	else
		return false;
}

template<typename T>
bool Stack<T>::isFull()
{
	if (top == _size)
		return true;
	else
		return false;
}

int _tmain(int argc, _TCHAR* argv[])
{
	Stack<char> s(1024);//更改<>里的类型与push的内容 实现类模版的多样性
	//Stack<char> 含义是对类模版实例化 使他变成想要的类
	//然后类 再实例化对象

	s.push('a');
	s.push('b');
	s.push('c');
	s.push('d');

	while (!s.isEmpty())
		cout << s.pop() << endl;

	return 0;
}

类模板和友元

       当一个类包含一个友元声明时,类于友元各自是否时模板时相互无关的,如果一个类模板包含一个非模板友元,则友元函数被授权可以访问所有模板实例,如果友元自身是模板,类可以授权给所有友元模板实例,也可以只授权给特定实例。

类模板的static成员

与任何其他类相同,类模板可以声明static成员,在这段代码中,Foo是一个类模板,每个Foo的实例都有其自己的static成员实例,即对任意给定类型X都有有一个Foo<X>::ctr和一个Foo<X>::count成员,所有Foo<X>类型的对象共享相同的ctr对象和count函数,对于Foo<int> fi,fi2,fi3;  所有3个对象共享相同的Foo<int>::ctr和Foo<int>::count成员。

template<typename T>
class Foo
{
public:
	static std::size_t count() { return ctr; }
private:
	static std::size_t ctr;
};

template<typename T>
size_t Foo<T>::ctr = 0; //定义并初始化ctr

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值