1. 目标
1.掌握继承与多态
2.掌握纯虚函数与抽象类以及接口的含义
3.通过多态的形式,建立与类型无关的通用链表
4.理解继承、组合以及聚合之间的关系
5.理解委托(Proxy)/代理(Deletgate)模式
2. 功能
从通用动态数组到通用链表。
实现一个通用的链表,可以存放各种继承Object
的对象。
3. 复用
3.1 继承(Inheritance)
继承是一个类(子类)继承另外的一个类(基类)的属性与方法。
3.2 组合(Composition)
组合是类之间整体和部分的关系。整体与部分有相同的生存周期。
3.3 聚合(Aggregation)
聚合是类之间整体和部分的关系。部分生存周期比整体的长。
3.4 小结
关系 | 含义 | UML表示方式 |
---|---|---|
继承 | is-a |
空心三角 |
组合 | contains-a |
实心菱形 |
聚合 | has-a |
空心菱形 |
从某种意义上说,继承是一种类的纵向关系,而聚合,组合是对象的横向关系。
4. 委托(Proxy)/代理(Deletgate)模式
在委托/代理模式中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。具有现有对象的对象,以便向外界提供功能接口。
5. 参考实现
#include <cassert>
#include <cstring>
#include <iostream>
using namespace std;
class Object {
public:
Object(){}
virtual ~Object(){}
virtual void Print() const= 0;
};
class ListNode {
friend class List;
public:
ListNode(Object *pobj = NULL);
~ListNode();
private:
Object *pData; //父类类型作为子类的接口类型
ListNode *pNext;
};
ListNode::ListNode(Object *pobj /*= NULL*/) : pData(pobj), pNext(NULL) {}
ListNode::~ListNode(){delete pData;}
class List {
public:
List();
~List();
void PushBack(Object *pb);
void Print()const;
private:
ListNode *pHead;
ListNode *pTail;
};
List::List():pHead(new ListNode),pTail(pHead){}
List::~List(){
ListNode *p = pHead->pNext;
while(p != NULL) {
pHead->pNext = p->pNext;
delete p;
p = pHead->pNext;
}
delete pHead;
pHead = pTail = NULL;
}
void List::PushBack(Object *pb) {
ListNode *pNode = new ListNode(pb);
assert(NULL != pNode);
pTail->pNext = pNode;
pTail = pNode;
}
void List::Print() const{
}
class Integer : public Object {
public:
Integer(int data = 0):data(data){}
virtual void Print(){
cout << data;
}
private:
int data;
};
Integer::Integer(int data /*= 0*/):data(data){}
virtual void Integer::Print()const{
cout << data;
}
class String : public Object {
public:
String(const char *str = NULL);
virtual void Print()const;
~String();
private:
char *data;
};
String::String(const char *str = NULL){
if(str == NULL) {
data = new char[1];
data[0] = '\0';
} else {
data = new char[strlen(str)+1];
strcpy(data,str);
}
}
/*virtual*/ void String::Print()const { cout << data; }
String::~String() {
delete [] data;
data = NULL;
}
int main() {
List mylist;
for(int i = 1; i <= 5; ++i) {
Integer *pi = new Integer(i);
mylist.PushBack(pi);
}
// mylist.PrintList();
List youlist;
char *str[] = {"xsy","sfds","sdfsf","sfdsfs","sdfsf"};
for(int j = 0; j < 5; ++j){
String *ps = new String(str[j]);
youlist.PushBack(ps);
}
// youlist.PrintList();
return 0;
}
参考代码中有几处语法错误,请大家尝试修改。
6. 扩展
Object
添加如下接口
No. | 函数 | 功能 |
---|---|---|
1 | string ToString() |
对象转化成字符串 |
2 | Object Clone() |
复制对象 |
3 | bool Equal(const Object& obj) |
判断对象是否相等 |
7. 作业(项目)
内容
- 设计文档
要求 | 说明 |
---|---|
格式 | markdown |
内容 | 概要说明、功能、UML类图 |
UML绘制工具:visio、starUML、在线ProcessOn
功能
在通用链表基础上,把Bank/Account、Student/Subject、Shape(Triangle、Rect ...)/ShapeManager整合到里面。工程结构
目录 | 作用 |
---|---|
include | 存放头文件 |
src | 存放源文件 |
test | 存放测试代码文件 |
doc | 存放文档 |
Makefile | 编译文件 |
- 编码规范
不能使用汉语拼音和没有意义的字母数字拼接。
MS C++编码规范
分类 | 格式 |
---|---|
类名 | 必须以大写C开头,首字母大写 |
成员变量 | 必须以m_ 开头,后面进接首字母小写 |
成员函数 | 必须首字母大写 |
局部变量 | 首字母小写 |
google C++编码规范
分类 | 格式 |
---|---|
类名 | 首字母大写 |
成员变量 | 首字母小写必须以_ 结尾 |
成员函数 | 必须首字母大写 |
局部变量 | 首字母小写 |
使用Astyle对代码进行格式化。
- 注释
使用doxygen注释方式对文件、类、函数、成员变量添加注释。并且生成注释文档放在doc
- 单元测试
覆盖率