封装前的考虑
在C++中有很丰富的库,当属STL模板,STL的设计和优化都为我们提供了应有的功能。然而对于新手而言,尝试进行一个封装,会使得自己更加熟悉面向对象。
面向对象三大特性:封装、继承、多态。这也是面向对对象语言相对面向过程而言,最大的优势和特点。面向对象使得程序更加利于维护,让设计人员更加关注设计,要想真正的理解面向对象的特性,则必须要清楚和掌握这三大规律。
在C++中,STL提供了Vector类,表示向量,其本质则是线性表的实现,并且可以在内部实现自动扩容,并且借助迭代器,可以很方便很快速的对表中元素进行访问和遍历。
因此我们手动封装的线性表,可以有以下的功能:
- 自动扩容
- 迭代器访问元素
- 下标式快速访问元素值
- 移除元素
- 增加元素
- 长度管理
上述这些功能,都是需要一个向量所需要提供的功能,并且基于面向对象的设计而言,采用迭代器模式的设计,可以很好的减小容器对象与数据之间的紧密耦合,通过迭代器去遍历向量表,可以很大程度的增加遍历的安全性和便利性。
在该设计中,可进行三个类的设计: Sequeence 抽象基类,ZArray类,Iterator 抽象基类, ZArrayIterator类,其中两个抽象基类中分别提供了序列类的基本操作,增删查改等,Iterator基本定义了迭代器的方法接口,可以很好的实现多态,并且可以拥有很好的扩展性,因为对序列数据容器而言,其逻辑结构可以是连续的向量式的,也可以是链式的,由此他们之间的遍历方式都不同,访问方式也不同,因此为了可扩展性,可以进行抽象,使得迭代器和序列容器进行交互,而无需使用具体的子类,并且可以很好的进行扩展。那么在这里,面向对向的特性则充分包含了进去,封装是完好类设计的基础,继承则是扩展的必经之路,多态则是在面向抽象编程的基础。
值得注意的是,由于在C++中容器类都采用模板的方式去进行封装,由此需要注意的是,最好将.h的定义和.cpp的定义为一个文件中,否则在某些编译环境中可能造成link错误!
学会如何去抽象
- 首先我们进行Sequence类的抽象定义
//
// Sequence.hpp
// Array
//
// Created by 邹智鹏 on 16/7/3.
// Copyright © 2016年 Frank. All rights reserved.
//
#ifndef Sequence_hpp
#define Sequence_hpp
#include <stdio.h>
#include "Iterator.hpp"
namespace ZTemplate {
typedef unsigned int z_size; // 用于表示大小,为无符号整形
typedef long rank; // 用于表示秩
template<class T>
class Sequence {
public:
/**
* 定义函数指针,用于表示两个值的比较, 若两个值相等,返回0,若val1 > val2 返回1, 否则返回-1
*/
typedef int (*__FUNC_COMPARE_)(const T &val1, const T &val2);
/**
* 插入到最后一个位置
*/
virtual void push_back(const T& val) = 0;
/**
* 从指定位置中,移除元素,并返回该元素的副本,若为指针,请自行进行内存管理
* @param pos 元素位置
* @return 返回该元素值
*/
virtual T pop(const rank pos) = 0;
/**
* 访问指定位置的值
* @param pos 元素所在的位置
* @return 返回该位置的元素值
*/
virtual const T &at(const rank pos) const = 0;
/**
* 移除指定位置元素
* @param pos 元素所在位置
* @return 返回是否移除成功
*/
virtual bool remove(const rank pos) = 0;
/**
* 根据指定值,在序列中进行查找,若查找到符合条件的则进行移除
*/
virtual bool remove(T &val1, __FUNC_COMPARE_ compare);
/**
* 获取迭代器
* @return 返回迭代器
*/
virtual Iterator<T> &iterator() = 0;
/**
* 重载访问器
* @param pos 元素位置
* @return 返回元素引用
*/
virtual T& operator[](const rank pos) = 0;
protected:
};
}
template<class T>
bool ZTemplate::Sequence<T>::remove(T &val1, __FUNC_COMPARE_ compare) {
Iterator<T> &curIterator = iterator(); // 获取到迭代器实例
bool found = false;
rank i = 0; // 秩
while (!found && curIterator.hasNext()) {
if (compare(val1, curIterator.data()) == 0) {
// 两者值相等
found = t