抽象数据类型ADT

Stock类非常具体。然而,程序员常常通过定义类来表示更通用的概念。例如:就实现计算机专家们所说的抽象数据类型(abstreact data type, ADT)而言,使用类是一种非常好的方式。
顾名思义,ADT以通用的方式描述数据类型,而没有引入语言或实现细节。例如:通过使用栈,可以以这样的方式存储数据,即总是从堆顶添加或删除数据。例如,C++程序使用栈来管理自动变量。当新的自动变量被生成后,它们被添加到堆顶;消亡时,从栈中删除它们。
下面简要的介绍一下栈的特征。首先,栈存储了多个数据项(该特征使得栈成为一个容器——一种更为通用的抽象);其次,栈由可对它执行的操作来描述。
 可创建空栈。
 可将数据项添加到堆顶(压入)。
 可从栈顶删除数据项(弹出)、
 可查看栈是否填满。
 可查看栈是否为空。
可将上述描述转换为一个类声明,其中公有成员函数提供了表示栈操作的接口,而私有数据成员负责存储栈数据。类概念非常适合于ADT方法。
私有部分必须标明数据存储的方式。例如,可以使用常规数组、动态分配数组或更高的数据结构(如链表)。然而,公有接口应隐藏数据表示,而以通用的术语来表达,如创建栈、压入等。程序清单10.10演示了一种方法,它假设系统实现了bool类型。如果您使用的系统没有实现,可以使用int 0和1代替bool false和true。

//stack.h -- class definition for the stack ADT
#ifndef STACK_H_
#define STACK_H_
typedef unsigned long Item;
class Stack
{
private:
	enum { MAX = 10 };	//constant specific to class
	Item items{ MAX };	//holds stack items
	int top;	//index for top stack item
public:
	Stack();
	bool isempty() const;
	bool isfull() const;
	//push()returns false if stack already is full, true otherwise
	bool push(const Item& item);	//add item to stack
	//pop() returns false if stack already is empty, true otherwise
	bool pop(Item& item);	//pop top into item
};
#endif

在上面程序中,私有部分表明,栈是使用数组实现的;而公有部分隐藏了这一点。因此,可以使用动态数组来代替数组,而不会改变类的接口。这意味着修改栈的实现后,不需要重新编写使用栈的程序,而只需重新编译栈代码,并将其与已有的程序代码链接起来即可。
接口是冗余的,因为pop()和push()返回有关栈状态的信息(满或空),而不是viod类型。在如何处理超出栈限制或者清空栈方面,这为程序员提供了两种选择。他可以在修改栈前使用isempty()和isfull()来查看,也可以使用push()和pop()的返回值里确定操作是否成功。
这个类不是根据特定的类型来定义栈,而是根据通用的Item类型来描述。在这个例子中,头文件使用typedef用Item代替unsigned long。如果需要double栈或结构类型的栈,则只需修改typedef语句,而类声明和方法定义保持不变。类模板提供了功能更强大的方法,来讲存储的数据类型与类设计隔离开来。
接下来需要实现类方法,程序清单10,11提供了一种可行的实现。

//程序清单10.11
//stack.cpp -- Stack member functions
#include"stack.h"
Stack::Stack()	//create an empty stack
{
	top = 0;
}
bool Stack::isempty()const
{
	return top == 0;
}bool Stack::isfull()const
{
	return top == MAX;
}
bool Stack::push(const Item& item)
{
	if (top < MAX) {
		items[top++] = item;
		return true;
	}
	else
		return false;
}
bool Stack::pop(Item& item)
{
	if (top > 0)
	{
		item = items[--top];
		return true;
	}
	else
		return false;
}

默认构造函数确保所有栈被创建时都为空。pop()和push()的代码确保栈顶被正确的处理。这种保证措施是OOP更可靠的原因之一。假设要创建一个独立数组来表示栈,创建一个独立变量来表示栈顶索引。则每次创建新栈时,都必须确保代码是正确的。没有私有数据提供的保护,则很可能由于无意修改了数据而导致程序出现非常严重的故障。
下面来测试栈。程序清单10.12模拟了售货员的行为——使用栈的后进先出方式,从购物筐的最上面开始处理购物订单。

//程序清单10.12 stacker.cpp
// stacker.cpp -- testing the Stack class
#include<iostream>
#include<cctype>//or ctype.h
#include"stack.h"
int main()
{
	using namespace std;
	Stack st;	//create an empty stack
	char ch;
	unsigned long po;
	cout << "Please enter A to add a purchase order,\n"
		<< "P to process a PO, or Q to quit.\n";
	while (cin >> ch && toupper(ch) != 'Q') {
		while (cin.get() != '\n')
			continue;
		if (!isalpha(ch))
		{
			cout << '\a';
			continue;
		}
		switch (ch)
		{
		case 'A':
		case'a':cout << "Enter a PO number to add: ";
			cin >> po;
			if (st.isfull())
				cout << "stack already full\n";
			else
				st.push(po);
			break;
		case 'P':
		case'p':if (st.isempty())
			cout << "stack already empty\n";
			   else {
			st.pop(po);
			cout << "PO #" << po << " popped\n";
		}break;

		}cout << "Please enter A to add a purchase order,\n"
			<< "P to process a PO, or Q to quit.\n";
	}cout << "Bye.\n";
	return 0;
}

程序清单10.12中的while循环删除行中剩余部分,就现在而言这并非是必不可少的,但它使程序的修改更方便。

总结:
私有数据成员存储信息,公有成员函数(又称为方法)提供访问数据的唯一途径。类将数据和方法组合成一个单元,其私有性实现数据隐藏。
通常,将类声明分成两部分组成,这两部分通常保存在不同的文件中。类声明(包括由函数原型表示的方法)应放到头文件中,。定义成员函数的源代码放在方法文件中。

	---From 《C++ Primer Plus》
	--	by Suki
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值