基类的虚函数在派生类中再定义称为函数的“覆盖(overriding)”,与“重载(overload)”是不同的2个概念,不要混淆。重载对类适用,对普通函数也适用,重载函数的参数一定是不相同的。覆盖只适用于类,并且是基类与派生类之间的重定义,其参数甚至返回值必须完全相同。
虚函数或纯虚函数自身并不实现任何功能,各个不同的类在继承时才实现不同的功能,因此,同一个虚函数在执行时具有了多种不同功能,称之为“多态”。
小雅以前在为单位面试新人时,有很多人对面向对象还很模糊,便自称精通C++,这是不可取的。理解了类、抽象类的思想还只能算入门,只有在不断实践中掌握更多的设计方法以及各种设计Pattern,才能算真正的C++程序员。
因这部分内容比较重要,本章不介绍新内容,只举例来加深理解。
基类里定义三个函数:设置区域数据setData()、取区域数据getData、求面积(虚函数)getArea。所谓数据,定义2个成员变量dim1和dim2,对于长方形来说是长和宽,对于三角形来说是底和高。
设计2个派生类,1个是长方形rectangle、1个是三角形triangle。要点是对getArea函数实装。
#include
<iostream>using namespace
std;class
area {double
dim1, dim2;public
: //设置数据void
setData(double
d1,double
d2) { dim1 = d1, dim2 = d2; } //取数据void
getData(double
& d1,double
& d2) { d1 = dim1, d2 = dim2; } //求面积virtual double
getArea() = 0; //纯虚函数 }; //长方形class
rectangle :public
area {public
:double
getArea() {double
d1, d2; getData(d1, d2);return
d1 * d2 ; } }; //三角形class
triangle :public
area {public
:double
getArea() {double
d1, d2; getData(d1, d2);return
d1 * d2 / 2 ; } };int
main ( ) { area *p; rectangle r; //长方形类的实例 triangle t; //三角形类的实例 r.setData(35, 44); t.setData(36, 25); p = &r; cout << "长方形的面积为: " << p->getArea() << endl; p = &t; cout << "三角形的面积为: " << p->getArea() << endl;return
0; }
队列和堆栈都是链表类型(可以参考“C语言教程”中的22章),它和数组不同的是个数是不定的,因此必须用指针来“记住”开始、末尾和下一个的位置。因此基类中有三个指针head、tail、next成员变量。还有一个成员变量num用来表示当前插入的值。另外定义2个纯虚函数store()和retrieve()来表示存贮(即增加)一个元素、处理(减少)一个元素,这是要编程的要点。
派生类里面要实现2个功能,即增加节点、删除节点。增加时首先new一个节点并对num赋值,然后修改链表的三个指针。而删除时要先修改链表的三个指针,然后再删除节点。
队列和堆栈的不同处是:队列是先进先出、后进后出;而堆栈则是先进后出、后进先出。这就是修改三个链表指针时要注意的地方。这需要有一点数据结构方面的知识。
#include
<iostream>#include
<cstdlib>#include
<cctype>using namespace
std;class
list {public
: list *head; //头指针 list *tail; //尾指针 list *next; //下一个指针int
num; //当前节点的值 list() { head = tail = next = NULL; } //构造函数virtual void
store(int
i) = 0; //增加节点virtual int
retrive() = 0; //删除节点 }; //队列class
queue :public
list {public
: //增加节点virtual void
store(int
i) { list *item =new
queue;if
(!item) { cout << "内存分配失败!" << endl; exit(1); } item->num = i; //链表末尾插入if
(tail) tail->next = item; tail = item; item->next = NULL;if
(!head) head = tail; } //取值并删除节点int
retrive() {int
i; list *p;if
(!head) { cout << "链表已经为空" << endl;return
0; } //从链表头部删除 i = head->num; p = head; head = head->next;delete
p;return
i; } }; //堆栈class
stack :public
list {public
: //增加节点virtual void
store(int
i) { list *item =new
stack;if
(!item) { cout << "内存分配失败!" << endl; exit(1); } item->num = i; //链表头部插入if
(head) item->next = head; head = item;if
(!tail) tail = head; } //取值并删除节点int
retrive() {int
i; list *p;if
(!head) { cout << "链表已经为空" << endl;return
0; } //从链表头部删除 i = head->num; p = head; head = head->next;delete
p;return
i; } };int
main ( ) { list *p; //队列的演示 queue q; p = &q; p->store(111), p->store(222), p->store(333); cout << "队列: "; cout << p->retrive() << " "; cout << p->retrive() << " "; cout << p->retrive() << endl; //堆栈的演示 stack s; p = &s; p->store(111), p->store(222), p->store(333); cout << "堆栈: "; cout << p->retrive() << " "; cout << p->retrive() << " "; cout << p->retrive() << endl;return
0; }