c++(三)【类模板】

【1】类型进行参数化,模板的意义是什么?

  • 可以定义类型变量,来接受用户传入的类型

template<> : 定义模板参数列表

typename T,typename E, typenameR  :类型变量,可以定义很多,用逗号分隔

     eg:   template<typename T>

类模板  =》 实例化 =》模板类

【2】模板的代码,在没有实例化之前,是不编译的

【3】类模板的选择性实例化         <最后附上代码>

  • 类模板实现链表
  • 类模板实现循环队列
  • 类模板实现优先级队列(大根堆)

*****   指针,引用,const   *****

C语言中:

  • const是个常变量

c++中:

  • const可以作为常量    (  所有使用常量名字的地方,都被常量的值替换了  )                                                                                        直接初始化, 如:const int a = 10; 此处a是常量
  • 也可以作为常变量    (看初始值是不是一个立即数    10     20     30)                                                                                                 赋的值是一个变量,如:int a = 10; const int b = a;  此处b为常变量                                                 

const和一级指针的结合        const修饰的 常量或常变量 都是保证不能被直接或间接的修改

int a =10 ;     int *p =&a ;

const  int b = 20 ;//此处b是个常量   const int * p2 = &b;

const和引用的结合

【1】

int a ;    int &b =a;   // 一般情况下,不允许给&b直接赋一个常量         例如  int & b =10;  这是不被允许的。会报错

const  int &b = 10;  //常引用。前面加const,才可以给他赋常量        可以用下面的方法理解,按理说&b是会保存10 的地址                                                              并且也是可以修改值的。但是10是一个常量,肯定不会让你修改,所以必须加const

【2】

const int a = 10;    const int &b = a;  // 此处必须加const , 因为给&b 赋的值为a,a属于常变量,所以不允许b访问并修改他                                                              的值,除非&b 加个const 限定。保证不会修改

int c =20;   const int d = c;    const int &e = d;

   只要是定义指针或者引用等可以访问常量或常变量地址的,给其赋常量或常变量时。都必须加const ,从而保证不会修改

用临时对象初始化同类型新对象的时候,临时对象就不产生了,用构造临时对象的方式,直接构造新对象       -------------->      Test  t1= Test(10,10) 

t1= 10;   要生成临时对象  int=>Test 

其他类型     =>     类类型       Test(int)

类类型      =>     其他类型      对其他类型提供类型重载函数

Test t1(10, 10);	  
 //地址变化00DB032C Test(int, int)
int main()
{	
	Test t2(20, 20);//构造t2   ma=20;mb=20;      
//地址变化 0046FC94  Test(int, int)
	Test t3 = t2;	//拷贝构造      
//地址变化 0046FC94=>0046FC84
	static Test t4 = Test(30, 30);	//构造t4 ma=30;mb=30; 
//地址变化 00DB0334 Test(int, int)
	t2 = Test(40, 40);//先构造test临时对象,ma=mb=40;再调用赋值函数,再析构test     
//地址变化0046FAE4 Test(int, int)   0046FAE4=>0046FC9 operator=   0046FAE4  ~Test()
	t2 = (Test)(50, 50);//构造test临时对象,ma=50,mb=5;再调用赋值函数,再析构test
//地址变化0046FAF4 Test(int, int)   0046FAF4=>0046FC94 operator=   0046FAF4  ~Test()
	t2 = 60;//调用构造函数,构造临时对象,ma=60,mb=5。然后赋值,然后析构临时 
//地址变化0046FB04 Test(int, int)    0046FB04=>0046FC94 operator=     0046FB04  ~Test()
	Test *p1 = new Test(70, 70);//构造  堆上 ma=mb=70      
//地址变化0089DFD8 Test(int, int)
	Test *p2 = new Test[2];	//2次构造  堆上 但是ma=mb=5;       
//地址变化0089C64C Test(int, int)        0089C654 Test(int, int)
	Test *p3 = &Test(80, 80);//构造  析构   
//地址变化0046FB44 Test(int, int)        0046FB44 ~Test()
        Test &p4 = Test(90, 90);//构造 
//地址变化0046FC44  Test(int, int)
	delete p1;          //地址变化0089DFD8 ~Test()
	delete[]p2;         //地址变化0089C654 ~Test()       0089C64C ~Test()
}                           //地址变化0046FC44~Test()   析构&p4指向的临时对象

Test t5(100, 100);            
//地址变化00DB0320 Test(int, int)

//构造t1  t5   t2   t3   t4 
//析构t3  t2   t4   t5   t1

/*
t1:Test(int, int)	t5:Test(int, int)	
t2:Test(int, int)	t3:Test(const Test&)	t4:Test(int, int)
临时:Test(int, int) operator= ~Test()
临时:Test(int, int) operator= ~Test()
临时:Test(int, int) operator= ~Test()
临时:Test(int, int)  ~Test() p1 Test(int, int)
临时:Test(int, int) Test(int, int) p2 Test(int, int)~Test()~Test()
临时:Test(int, int) p3 Test(int, int)
临时:Test(int, int) ~Test()
p1 ~Test() p2 ~Test()
p3 ~Test() 临时~Test()
t3~Test() t2~Test() t4~Test() t5~Test() t1~Test()
*/
//栈

template<typename T=int>
class CStack         
{
public:
	CStack(int size = 10);
	~CStack();
	void push(const T &val);
	void pop();
	T top();
	bool full() { return _top == _size; }
	bool empty() { return _top == 0; }
private:
	T *_pStack;
	int _top;
	int _size;
};
template<typename T = int>
CStack<T>::CStack(int size)
:_size(size), _top(0)
{
	_pStack = new T[_size];
}
template<typename T = int>
CStack<T>::~CStack()
{
	delete[]_pStack;
	_pStack = NULL;
}
template<typename T = int>
void CStack<T>::push(const T & val)
{
	if (full())
	{
		T *ptmp = new T[_size * 2];
		for (int i = 0; i < _size;i++)
		{
			ptmp[i] = _pStack[i];   //  高级代码 =》 汇编码
		}
		_size *= 2;
		delete _pStack;
		_pStack = ptmp;
	}
	_pStack[_top++] = val;
}
template<typename T>
void CStack<T>::pop()
{
	if (empty())
	{
		return;
	}
	_top--;
}
template<typename T>
T CStack<T>::top()
{
	return _pStack[_top - 1];
}
//大根堆实现优先级队列
template<typename T>
class PriorityQueue
{
public:
		// PriorityQueue p1; PriorityQueue p2(20)
		PriorityQueue(int size = 15);
		~PriorityQueue();
		void push(const T &val);  // 入优先级队列
		void pop();         // 出优先级队列
		T top();		    // 获取堆顶元素
		int Size();			// 返回优先级队列元素的个数
		bool full();		// 判断满
		bool empty();		// 判空
private:
		T *_pQue;
		int _cur;
		int _size;			// 记录队列增长的长度值

		void siftUp(int i, const T &val)   // 堆的上浮函数
		{
			while (i > 0)     // i表示当前节点
			{
				int p = (i - 1) / 2;    // p表示i节点的父节点
				if (val > _pQue[p]){
					_pQue[i] = _pQue[p];
					i = p;
				}
				else{
					break;
				}
			}
			_pQue[i] = val;
		}

		void siftDown(int i, const T &val)
		{
			// i表示父节点   k表示左孩子
			for (int k = 2 * i + 1; k < _cur; k = 2 * k + 1)
			{
				//右孩子值如果大于左孩子,则调整k为右孩子的下标
				if (k + 1 < _cur && _pQue[k] < _pQue[k + 1]){
					k++;
				}

				//k一定表示的是值最大的孩子的下标
				if (val < _pQue[k]){
					_pQue[i] = _pQue[k];
					i = k;
				}
				else{
					break;
				}
			}
			_pQue[i] = val;
		}
};
template<typename T>
PriorityQueue<T>::PriorityQueue(int size)
:_front(0), _rear(0), _size(size)
{
_pQue = new T[_size];
}
template<typename T>
PriorityQueue<T>::~PriorityQueue()
{
delete _pQue;
_pQue = NULL;
}
template<typename T>
void PriorityQueue<T>::push(const T &val)
{
if (full())  //如果满了,2倍内存扩容
{
T *ptmp = new T[_size * 2];
for (int i = _front; i != _rear; i = (i + 1) % _size)
{
for (int j = 0; j < _size; j++)
{
ptmp[j] = _pQue[i];
}
}
_size *= 2;
delete _pQue;
_pQue = ptmp;
_front = 0;
_rear = _size;
}
//从刚入队那个数开始和其父结点比较,如果大于父结点的值,则交换
_pQue[_rear] = val;
for (int i = (_rear-1) / 2; i >=0; i--)
{
Adjust(_pQue, i, _rear);
}
_rear = (_rear + 1) % _size;
}

template<typename T>
void PriorityQueue<T>::pop()
{
if (empty())
{
return;
}
_front = (_front + 1) % _size;
}
template<typename T>
T PriorityQueue<T>::top()
{
return _pQue[_front];
}
template<typename T>
bool PriorityQueue<T>::full()
{
return (_rear + 1) % _size == _front;
}
template<typename T>
bool PriorityQueue<T>::empty()
{
return _rear == _front;
}
template<typename T>
int PriorityQueue<T>::Size()
{
return _rear - _front;
}
//单链表
template<typename T = int>
class Link
{
public:
	Link();
	~Link();
	void insert(const T &val);
	void remove(const T &val);
	void show();
private:
	// 嵌套类
	struct Node
	{
		Node(T val = T()) :_data(val), _next(NULL){}
		T _data;
		Node *_next;
	};

	// 指向头结点的指针
	Node *_head;
};
template<typename T = int>
Link<T>::Link()
{
	_head=new Node();
}
template<typename T = int>
Link<T>::~Link()
{
	Node *pdel = NULL;
	while (_head->_next != NULL)
	{
		pdel=_head->_next;
		_head->_next=pdel->_next;
		delete pdel;
		pdel=NULL;
		_head->_next=NULL;
	}
	delete _head;
}
template<typename T = int>
void Link<T>::insert(const T &val)
{
	Node *pcur = _head;
	while (pcur->_next != NULL)
	{
		pcur = pcur->_next;
	}
	pcur->_next = new Node(val);
}
template<typename T = int>
void Link<T>::remove(const T &val)
{
	Node*p = _head; Node*pcur=_head->_next;
	while (pcur != NULL)
	{
		if (pcur->_data == val)
		{
			p->_next=pcur->_next;
			delete pcur;
			pcur=p->_next;
		}
		else
		{
			p = pcur;
			pcur = pcur->_next;
		}
	}
}
template<typename T = int>
void Link<T>::show()
{
	Node*p = _head->_next;
	while (p != NULL)
	{
		cout << p->_data << endl;
		p = p->_next;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_42212982/article/details/81533862