模板栈(一)

1. 模板函数

template<class Type>
class SeqStack
{
private:
	Type *data;
	int size;
	int top;
}
class String
{}
int main()
{
	SeqStack<int> ist;
	SeqStack<double> dst;
	SeqStack<String> sst;
	return 0;
}

总结

  1. 模板函数的格式要求:第一行需要添加:template,在使用模板函数时:SeqStack<数据类型> ist;
  2. 模板函数的作用:使得函数更具有通用性,Type表示使用模板函数的数据类型,如果是整型数据,则在函数中,Type类型的数据为整型数据,如果是double类型,Type类型的数据为double类型;
  3. 任何数据类型都可以使用模板函数,即使是自己定义的函数也可以作为类型使用模板函数;
  4. 在使用模板函数时,是对模板函数进行重命名,而不是宏替换。
//将SeqStack重命名为:
class SeqStack<int>
{
	typedef int Type;
private:
	Type *data;
	int size;
	int top;
}

2. 模板栈

在栈中,一般具有以下几个函数:
构造函数、析构函数、入栈、出栈、得到栈顶元素、判空、得到栈中元素
此模块为简单模板栈的编写:

template<class Type>
class SeqStack
{
private:
	Type *data;   //指向所存储的数据
	int capacity;//栈容量
	int pos;     //栈顶
public:
	SeqStack(int sz = 100):data(NULL),capacity(sz),pos(-1)//构造函数,初始化private成员
	{
		data = new Type[capacity];//通过new运算符申请空间,并调用构造函数;
	}
	void push(const Type &x)//入栈--改变对象状态,不能为常方法
	{
		data[++pos] = x;
	}
	void pop()//出栈--改变对象状态,不能为常方法
	{
		--pos;
	}
	Type & top()//得到栈顶元素
	{
		return data[pos];
	}
	const Type & top() const//得到栈顶元素
	{
		return data[pos];
	}
	bool empty() const//判空--不改变对象状态,常方法
	{
		return size() == 0;
	}
	size_t size() const//得到栈中元素--对象个数,不改变对象状态,常方法
	{
		return pos+1;
	}
	~SeqStack()//析构函数
	{
		delete []data;//释放空间
		data = NULL;
		capacity = 0;
		pos = -1;
	}
};

注意点

  1. size_t为无符号整型:unsigned int;
  2. 栈的容量和栈所含元素的个数是不同的概念;
  3. 成员方法和变量不能重命名;
  4. 两个得到栈顶元素函数的区别:
//例子:
class Object
{
private:
	int value;
public:
	Object(int x = 0):value(x){}
	~Object() {}
	//(1)int Value() { return value; }
	//(2)int & Value() { return value; } ----第一个top
	//改写为:int &Value(Object * const this) 
	//(3)int & Value() const { return value; }   //常方法
	//(4)----第二个top,常对象可以调用
	const int & Value() const { return value; }
}
int main()
{
	Object obj(100);
	int x = obj.Value();
	obj.Value() = 10;   // 改写后:Value(&obj) = 10;
	
	const Object obj2(10);  //常对象
	int y = obj2.Value();  
	
}

(1)当Value()方法返回类型为int型时,则是以值的形式返回:返回时会创建临时空间,只具有可读性,不能被修改,因此:obj.Value() = 10,不能成功;
(2)当Value()方法返回类型为int & 型时,则是以引用形式返回:obj.Value() = 10;相当于obj.value = 10;可以修改value的值;
(3)int & Value() { return value; }改写为:int &Value(Object * const this) ,表示this不能改变,但this的指向可以被改变,常对象不能被改变,因此当常对象调用此方法时,产生矛盾,需要添加const,改为常方法;
(4)int & Value() const此方法返回的是引用–this->value,表示可以被改变,而常方法不能被改变,产生矛盾,因此在返回值类型需要添加const;
(5)普通对象优先选择普通方法,再选择常方法,而常对象只能选择常方法;
(6)当成员函数不改变对象的状态时,将其设置为常方法,使得方法通用性更强。

检验:

int main()
{
	SeqStack<int> ist;
	for(int i=0;i<10;i++)
	{
		ist.push(i+10);
	}
	int x=0;
	while(!ist.empty())
	{
		x = ist.top();
		ist.pop();
		cout<<x<<endl;
	}
	return 0;
}

注意:
使用引用时可能会出现失效引用!!
下面进行举例说明:

//仍沿用上面模板
int main()
{
	SeqStack<int> ist;
	for(int i=0;i<10;i++)
	{
		ist.push(i+10);
	}
	while(!ist.empty())
	{
		int &a = ist.top();
		ist.pop();
		cout<<a<<endl;
	}
	return 0;
}

求问:a是否能够打印出?
在程序进行到调用ist.top()时,返回的是data[pos]本身,而a是data[pos]的引用,随后调用ist.pop()之后,pos-1,所以a指向的是pos-1的值,因而造成数据的丢失,形成失效引用。

本模块只是简单模板栈的编写,后续将会优化模板栈。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值