02~C++类模板

一 类模板定义

常常把 类模板 同 函数模板 进行比较。函数模板侧重实现不同类型的通用算法。
类模板相比下,首先具有容器的属性,描述了内存的开销与布局特点。

1. 简答的Stack类

设想分别这样定义Item
typename unsigned char Item;
typename short int Item;
甚至
typename struct Element Item;
这种形式,类类型 Element将会作为类型Stack的基本单元

#include <iostream>
using namespace std;
typedef unsigned long Item;
//typename unsigned char Item;
//typename short int Item;
struct Stack {
public:
	
		
	Stack (void) {
		int cnt = 0;
		top = 0;
		for (;cnt < MAX; cnt++)  {
			items[cnt] = 0;
		}
	}
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item const & item) {
	}
	bool pop (Item &item) {
	}
	
private:
   enum {MAX=10};
	int top;
	Item items[MAX];
};
int main (void) {
Stack st;
return 0;
}

2. 请对比上面示例代码

区别出在于抽象表示
不再使用typedef long Item 这种固定而难用的形式,而是使用抽象模板类型 template <>这种形式

其次在使用(调用)类模板时,需要显示指出容器单元的类型

#include <iostream>
using namespace std;
//不再使用typendef 的形式
template <typename Item>
struct Stack {
public:
	
		
	Stack (void) {
		int cnt = 0;
		top = 0;
		for (;cnt < MAX; cnt++)  {
			items[cnt] = 0;
		}
	}
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item const & item) {
	}
	bool pop (Item &item) {
	}
	
private:
   enum {MAX=10};
	int top;
	Item items[MAX];
};
int main (void) {
Stack<long int> st; //指出容器单元
//Stack <char> st;
//Stack <long long> st;
return 0;
}

二 例举类模板特殊使用方式

1. 模板接收整型类型参数

模板编译时:定义Items个数为MAX

#include <iostream>
using namespace std;
template <typename Item, int MAX>
struct Stack {
public:
	Stack (void) {
		int cnt = 0;
		top = 0;
		for (;cnt < MAX; cnt++)  {
			items[cnt] = 0;
		}
	}
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item const & item) {
	}
	bool pop (Item &item) {
	}
	
private:
	int top;
	Item items[MAX];
};
int main (void) {
Stack<long int,10> st; //指出容器单元 以及容器容量

return 0;
}

2. 动态分配内存

使用动态内存分配方法,修改Stack的设计结构

#include <iostream>
using namespace std;
template <typename Item>
struct Stack {
public:
	//改用动态内存分配
	Stack (int nums) : size(nums), item (NULL){
		item = new Item[nums];
	}
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item const & item) {
	}
	bool pop (Item &item) {
	}
	~ Stack(void) {
		if(item)
		delete [] item;
	}
private:
	int top;
	int size;//records the max element nums
	Item* item; // holds the elements
};
int main (void) {
//通过构造函数提供需要的容器 容量
Stack<long int> st(10); //指出容器单元 以及容器容量
return 0;
}

3. 类模板的递归

递归调用通常是用来描述类似多维数组这样的结构

Stack<int, 10> st1,表示了一个一维的Stack结构(由10个int组成)
访问方法:一维数组成员访问形式如下:st1. items[0] , st1.items[1]

Stack< Stack<int,10>,20 > st2,表示由20个一维Stack 结构构成的二维结构,每一个一维结构由(10个int构成)
访问方法:
事实上,这种形式是由20个 单元类型为Stack<int, 10> 的模板类型
st2.items[0], st2.items[1], 表示的每一个Stack<int,10> 模板类
st2.items[0].items[0], st2.items[1].items[2],表示内层数据中的int

#include <iostream>
using namespace std;
template <typename Item, int MAX>
struct Stack {
public:
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item const & item) {
	}
	bool pop (Item &item) {
	}
public:
int top;
Item items[MAX];
};
int main (void) {
Stack<long int,10> st1; //指出容器单元 以及容器容量
Stack<Stack<int,10>,20> st2;

st1.items[0] = 100;
st2.items[0].items[9] = 200;
cout << "items one array " << st1.items[0] << endl;
cout <<"items double array " << st2.items[0].items[9] << endl;
return 0;
}

4. 使用多个类型参数

模板的一种使用技巧如下
template < typename type >
class classname {

}

猜测存在单一的类型形参不能满足设计需要的情况,因此诞生了多个类型参数的模板设计,形如
template < typename T1, typename T2>
class classname {

}
以下直接贴上C++ primer plus 一书提供的模板 Pair 实现

#include <iostream>
#include <string>

template <typename T1,  typename T2>
class Pair {
private:
T1 a;
T2 b;
public:
T1& first();
T2& second();
T1 first() const {return a;}
T2 sencond() const {return b;}
Pair(T1 const& aval, T2 const& bval) : a(aval), b(bval){}
Pair() {}
};

int main(void)
{
using namespace std;
Pair<string,int> Packages[4] {
	Pair<string, int>("The purple Duck", 5),
	Pair<string, int>("rabbits", 6),
	Pair<string, int>("rabbits", 7),
	Pair<string, int>("rabbits", 8),
};
int nums  = sizeof(Packages)/sizeof(Pair<string,int>);
cout << "nums  = " << nums << endl;
int cnt = 0;
for (;cnt < nums;cnt++) {
	cout << "cnt = " << cnt << " string = " << Packages[cnt].first() << endl;
}
return 0;
}
template <typename T1, typename T2>
T1& Pair<T1, T2>::first() {
	return a;
}
template <typename T1, typename T2>
T2& Pair<T1,T2>::second() {
	return b;
}

5. 类模板默认参数

#include <iostream>
using namespace std;
//默认单元类型为int ,默认个数为10
template <typename Item = int, int MAX = 10>
struct Stack {
public:
	Stack (void) {
		int cnt = 0;
		top = 0;
		for (;cnt < MAX; cnt++)  {
			items[cnt] = 0;
		}
	}
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item const & item) {
	}
	bool pop (Item &item) {
	}
	
private:
	int top;
	Item items[MAX];
};
int main (void) {
Stack<> st; //不给入 类型参数,使用默认类型参数
cout << "size = " << sizeof(st)  << endl; //40 + 4

return 0;
}

6. 模板重载

模板的具体化就形式上来看 同函数模板没有什么区别。直接示例作为参考即可

#include <iostream>
using namespace std;
template <typename Item, int MAX>
struct Stack {
public:
	Stack(void) {
		cout <<"general version " <<endl;
	}
private:
	int top;
	Item items[MAX];
};

//具体的char 单元设计方法 
template <int MAX>
struct Stack<char,MAX> {
public:
	Stack(void) {
		cout <<"char version " << endl;
	}
private:
	int top;
	char items[MAX];
};

//具体的使用指针的 设计方法
template <typename T, int MAX>
struct Stack<T *, MAX> {
public:
	Stack(void) {
		cout <<"Ptr version " << endl;
	}
private:
	int top;
	T* items[MAX];
};

int main (void) {
//通用方法
Stack<int,100> st; //general
Stack<char, 100> st_char; //char
Stack<char *, 100> st_ptr; //ptr
return 0;
}

7. 成员模板

Item 作为成员模板存在的。 他用来进一步封装实用易于管理的类型

#include <iostream>
using namespace std;
template <typename element, int MAX>
struct Stack {
public:
	template <typename V> 
	struct Item {
	V member;
	int state;
	};
	
	Stack (void) {
	}
	bool isempty() const{
	}
	bool isfull () const {
	}
	bool push (Item<element> const & item) {
	}
	bool pop (Item <element> &item) {
	}
	
private:
	int top;
	Item<element> items[MAX];
};
int main (void) {
return 0;
}

8. 类模板作为参数

  • 示例1
#include <iostream>
using namespace std;

template <typename V> 
struct Item {
V member;
int state;
};
   
template <template <typename T> class Item , int MAX>
struct Stack {
public:

   Stack (void) {
   }
   bool isempty() const{
   }
   bool isfull () const {
   }
   bool push (Item<int> const & item) {
   }
   bool pop (Item <int> &item) {
   }
   
private:
   int top;
   Item<int> items[MAX];
};
int main (void) {
return 0;
}
  • 示例 2
#include <iostream>
using namespace std;

template <typename V> 
struct Item {
V member;
int state;
};
   
template <template <typename T> class Item , typename element, int MAX>
struct Stack {
public:

   Stack (void) {
   }
   bool isempty() const{
   }
   bool isfull () const {
   }
   bool push (Item<element> const & item) {
   }
   bool pop (Item <element> &item) {
   }
   
private:
   int top;
   Item<element> items[MAX];
};
int main (void) {
return 0;
}

三 类模板与友元函数

1. 非模板友元函数

友元表示为特定的函数声明(G++编译器对此种语法表示一些警告)

#include <iostream>
using namespace std;
template <typename T>
class Container{
public:
	Container(T const& a , T const& b):m_c1(a),m_c2(b) {}
	//非模板形式的友元函数声明
	friend void show_mem(Container const& that);
private:
T m_c1;
T m_c2;
};
void show_mem(Container<int> const& that) {
	cout << that.m_c1 << ' ' << that.m_c2 << endl;
}
int main() {
Container<int> c1(10,20);
show_mem(c1);
return 0;
}

2. 友元函数

#include <iostream>
using namespace std;

/*声明show_mem为函数模板*/
template <typename T>
void show_mem(T const& that);

template <typename T>
class Container{
public:
	Container(T const& a , T const& b):m_c1(a),m_c2(b) {}
	//友元函数形参为模板的一种特化,这里也是叫做约束模板的原因
	friend void show_mem<>(Container<T> const& that);
private:
T m_c1;
T m_c2;
};


//给出 友元函数模板定义
template <typename T>
void show_mem(T const& that) {
	cout << that.m_c1 << ' ' << that.m_c2 <<endl;
}

int main() {
Container<int> c1(10,20);
show_mem(c1); //show_mem< Container<int> >
Container<double> c2(1.1,1.2);
show_mem(c2);//show_mem< Container<double> >
return 0;
}

3. 友元函数模板

#include <iostream>
using namespace std;

template <typename T>
class Container{
public:
	Container(T const& a , T const& b):m_c1(a),m_c2(b) {}
	//友元函数为通用模板
	template <typename D> friend void show_mem(D & that);
private:
T m_c1;
T m_c2;
};


//给出 友元函数模板定义
template <typename T>
void show_mem(T & that) {
	cout << that.m_c1 << ' ' << that.m_c2 <<endl;
}

int main() {
Container<int> c1(10,20);
show_mem(c1); //show_mem< Container<int> >
Container<double> c2(1.1,1.2);
show_mem(c2);//show_mem< Container<double> >
return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值