1.5.3 ADT的模板接口

2014-03-11 13:00:04 · 作者: · 浏览: 111

1.5.3  ADT的模板接口

当规范变得更加详细时,就应该选择编程语言了。最终,可以用C++为包中的方法编写原型,并将其组合到实现这个ADT的类的头文件中。

程序清单1-1中的C++头文件包含了关于ADT包的方法,并用注释详细描述了方法的行为。考虑到读者可能不熟悉C++类、模板以及虚方法,C++片段1提供了关于C++类的复习课程,并将讨论C++模板、虚方法以及抽象基类。通过使用模板以及抽象基类,可以利用面向对象设计的封装、多态以及继承的概念开始第一个ADT。

提示:为了强调设计ADT和用数据结构实现ADT的区别,本书在描述ADT的时候使用了模板和抽象基类。我们将包含抽象基类的头文件称为客户接口1。为了在程序中使用某个类,只需要客户接口,因为其中完整地指定了ADT的方法。

当检查程序清单1-1中的接口时,注意针对特殊情况所做的决定,在前面已经提到过这个问题。特别是,add、remove和contains都返回值。注意用来说明方法的注释以@开头,这一内容在附录I中描述。

现在,包中的项是同一类的对象。为了容纳任何同一类型项,包的方法为每个项使用了泛型类型ItemType。为了使标识符ItemType有意义,必须在类的头文件之前编写template<class ItemType>行。当客户选择了实际的数据类型之后,编译器将在出现ItemType的所有位置使用这一数据类型。

BagInterface类是C++抽象基类。C++中的抽象基类(或者简写为抽象类)至少包含一个虚方法,并且没有实现。抽象类无法被实例化,而是只能用作基类。子类必须实现在基类中说明但是没有定义的方法。

程序清单1-1  包含包的C++接口的文件
 

  1. /** @file BagInterface.h */  
  2. #ifndef _BAG_INTERFACE  
  3. #define _BAG_INTERFACE  
  4. #include <vector> 
  5. using namespace std;  
  6. template<class ItemType> 
  7. class BagInterface  
  8. {  
  9. public:  
  10. /** Gets the current number of entries in this bag.  
  11. @return  The integer number of entries currently in the bag. */  
  12. virtual int getCurrentSize() const = 0;  
  13. /** Sees whether this bag is empty.  
  14. @return  True if the bag is empty, or false if not. */  
  15. virtual bool isEmpty() const = 0;  
  16. /** Adds a new entry to this bag.  
  17. @post  If successful, newEntry is stored in the bag and  
  18. the count of items in the bag has increased by 1.  
  19. @param newEntry  The object to be added as a new entry.  
  20. @return  True if addition was successful, or false if not. */  
  21. virtual bool add(const ItemType& newEntry) = 0;  
  22. /** Removes one occurrence of a given entry from this bag,  
  23. if possible.  
  24. @post If successful, anEntry has been removed from the bag  
  25. and the count of items in the bag has decreased by 1.  
  26. @param anEntry  The entry to be removed.  
  27. @return  True if removal was successful, or false if not. */  
  28. virtual bool remove(const ItemType& anEntry) = 0;  
  29. /** Removes all entries from this bag.  
  30. @post  Bag contains no items, and the count of items is 0. */  
  31. virtual void clear() = 0;  
  32. /** Counts the number of times a given entry appears in bag.  
  33. @param anEntry  The entry to be counted.  
  34. @return  The number of times anEntry appears in the bag. */  
  35. virtual int getFrequencyOf(const ItemType& anEntry) const = 0;  
  36. /** Tests whether this bag contains a given entry.  
  37. @param anEntry  The entry to locate.  
  38. @return  True if bag contains anEntry, or false otherwise. */  
  39. virtual bool contains(const ItemType& anEntry) const = 0;  
  40. /** Empties and then fills a given vector with all entries that  
  41. are in this bag.  
  42. @return  A vector containing all the entries in the bag. */  
  43. virtual vector<ItemType> toVector() const = 0;  
  44. }; // end BagInterface  

这些操作的规范是ADT包的各项契约:如果要求这些操作执行,那么就会执行。规范中没有说明如何存储包或如何执行这些操作;而只是说明可以对包做什么。ADT的规范中不包含实现话题,这一点非常重要。对ADT规范的限制可以在ADT实现和使用ADT的程序(也就是客户)之间建立一堵墙。程序只应该依赖于操作的行为。

提示:尽管在实现类之前编写接口并非必要,但是这么做可以以简洁的方式编写规范。然后可以使用接口中的代码作为实际类的大纲。使用接口还可以为ADT提供不依赖于特定类定义的数据类型。第3章和第4章将开发包的不同实现类。类接口代码可以让您方便地用一个包实现替换另一个。