学过C语言或C++的同学可能很早就接触到一个名词:抽象数据类型,又名ADT(abstract data type)。
根据字面意思就知道,它是一种数据类型,就像基本数据类型int、char、double一样,某种数据类型的变量是用来存储数据的,抽象数据类型的变量也不例外,只不过它多了一种思想:数据抽象和封装。《C++ Primer 第5版》第7章:类,这章开始就介绍到:
类要想实现数据抽象和封装,需要首先定义一个抽象数据类型。
有意思的是,《C++ Primer 第6版》在介绍对象和类时,讲解方式做了调整,在给出ADT的概念之前,讲了很多其它内容,而不是上来就说什么是ADT。
首先,突出说明了面向对象编程对于数据的关注:
采用过程性编程方法时,首先考虑要遵循的步骤,然后考虑如何表示这些数据。如果换成一位OOP程序员,又将如何呢?首先考虑数据——不仅要考虑如何表示数据,还要考虑如何使用数据。
其次,像我上面说的,类其实是一种数据类型。书中首先分析类型是什么,指定基本类型后完成的三项工作:
1. 决定数据对象需要的内存数量;
2. 决定如何解释内存中的位;
3. 决定可使用数据对象执行的操作或方法。
然后说,基本数据类型由编译器决定上述3点行为,而类只不过是需要自己提供这些信息的类型。
再者,先给出一种具体的类接口的样子。一个表示股票的类接口:
// stock00.h -- Stock class interface
// version 00
#ifndef STOCK00_H_
#define STOCKOO_H_
#include <string>
class Stock // class declaration
{
private:
std::string company;
long shares;
double share_val;
double total_val;
void set_tot() { total_val = shares * share_val; }
public:
void acquire(const std::string & co, long n, double pr);
void buy(long num, double price);
void sell(long num, double price);
void update(double price);
void show();
}
#endif
一直到10.7节才开始讲抽象数据类型:
Stock类非常具体。然而,程序员常常通过定义类来表示更通用的概念。
给出的例子是:栈。
// stack.h -- class definition for the stack ADT
#ifndef STACK_H_
#define STACK_H_
typedef unsigned long Item;
class Stack
{
private:
enum { MAX = 10 };
Item items[MAX];
int top;
public:
Stack();
bool isempty() const;// 查看栈是否为空
bool isfull() const;// 查看栈是否填满
bool push(const Item & item); // 将数据项添加栈顶
bool pop(Item & item); // 从栈顶删除数据项
}
#endif
而我想说的是,不是只有类才可以实现抽象,抽象是一种思想,栈是一种「后进先出」的数据结构,JavaScript通过数组也可以模拟这种行为:
ECMAScript为数组专门提供了push()和pop()方法,以便实现类似栈的行为。
类似的,结合使用shift()和push()方法,可以像使用队列一样使用数组。而《C++ Primer 第6版》在介绍队列时说:对于队列操作而言,数组并不合适。
为什么在C++中实现队列,数组就不合适了呢?-_-