听弦断,断那三千痴缠。
坠花湮,湮没一朝风涟。
花若怜,落在谁的指尖
时间最苦,剪不断对你的思恋
记忆最甜,抹弯嘴角的朱颜。
不知故人现在何方?不知红颜为谁而断?
捧一把月光,吹落簌簌哀伤。相盼相望,顾影自怜。
白衣起舞,玉指轻弹,买醉花酒前。梦回流年,微雨双飞燕。。。。。。
其实很喜欢古文,因为意境很美,恬静、忧伤、凄迷、淡然,没有车水马龙,内心的平静,没有浮躁。
今天看了这个书的关于继承的这部分,就写点笔记噻
子类:(继承)
子类可以复用父类所有的设计和代码,
子类具有两大特点:
Specialize:
Note that specialization refers exclusively to changing the implementation of operations and not at all to the redefinition of data.
Extend:
the child class will have new features, such as new attributes or operations.
对于specialization: 可以使用上文中实现多态的switch-case条件判断,但是那种方法显得过于死板,也不是真正意义上的多态,我们有一种更灵活的方式来实现这一点-----函数指针
对于extension: 子类中包含父类的指针,于是子类的实例中就继承了父类所有的属性。
文中举了一个队列的例子,父类是Queue,派生出子类CachedQueue,见uml图表示:
我们来看一下具体实现代码:
父类:Queue
头文件Queue.h
#ifndef QUEUE_H_
#define QUEUE_H_
#define QUEUE_SIZE 10
/* class Queue */
typedef struct Queue Queue;
struct Queue {
int buffer[QUEUE_SIZE]; /* where the data things are */
int head;
int size;
int tail;
int (*isFull)(Queue* const me);
int (*isEmpty)(Queue* const me);
int (*getSize)(Queue* const me);
void (*insert)(Queue* const me, int k);
int (*remove)(Queue* const me);
//这些函数指针都是虚函数
};
/* Constructors and destructors:*/
void Queue_Init(Queue* const me,int (*isFullfunction)(Queue* const me),
int (*isEmptyfunction)(Queue* const me),
int (*getSizefunction)(Queue* const me),
void (*insertfunction)(Queue* const me, int k),
int (*removefunction)(Queue* const me) );
void Queue_Cleanup(Queue* const me);
//看起来实现的好复杂哦,是我见到的最长的初始化函数
/* Operations */
int Queue_isFull(Queue* const me);
int Queue_isEmpty(Queue* const me);
int Queue_getSize(Queue* const me);
void Queue_insert(Queue* const me, int k);
int Queue_remove(Queue* const me);
Queue * Queue_Create(void);
void Queue_Destroy(Queue* const me);
#endif /*QUEUE_H_*/
Queue 实现文件Queue.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
void Queue_Init(Queue* const me,int (*isFullfunction)(Queue* const me),
int (*isEmptyfunction)(Queue* const me),
int (*getSizefunction)(Queue* const me),
void (*insertfunction)(Queue* const me, int k),
int (*removefunction)(Queue* const me) ){
/* initialize attributes */
me->head = 0;
me->size = 0;
me->tail = 0;
/* initialize member function pointers */
me->isFull = isFullfunction;
me->isEmpty = isEmptyfunction;
me->getSize = getSizefunction;
me->insert = insertfunction;
me->remove = removefunction;
}
/* operation Cleanup() */
void Queue_Cleanup(Queue* const me) {
}
/* operation isFull() */
int Queue_isFull(Queue* const me){
return (me->head+1) % QUEUE_SIZE == me->tail;
}
/* operation isEmpty() */
int Queue_isEmpty(Queue* const me){
return (me->head == me->tail);
}
/* operation getSize() */
int Queue_getSize(Queue* const me) {
return me->size;
}
/* operation insert(int) */
void Queue_insert(Queue* const me, int k) {
if (!me->isFull(me)) {
me->buffer[me->head] = k;
me->head = (me->head+1) % QUEUE_SIZE;
++me->size;
}
}
/* operation remove */
int Queue_remove(Queue* const me) {
int value = -9999; /* sentinel value */
if (!me->isEmpty(me)) {
value = me->buffer[me->tail];
me->tail = (me->tail+1) % QUEUE_SIZE;
--me->size;
}
return value;
}
Queue * Queue_Create(void) {
Queue* me = (Queue *) malloc(sizeof(Queue));
if(me!=NULL)
{
Queue_Init(me, Queue_isFull, Queue_isEmpty, Queue_getSize,
Queue_insert, Queue_remove);
}
return me;
}
void Queue_Destroy(Queue* const me) {
if(me!=NULL)
{
Queue_Cleanup(me);
}
free(me);
}
测试程序:
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
int main(void) {
int j,k, h, t;
/* test normal queue */
Queue * myQ;
myQ = Queue_Create();
k = 1000;
for (j=0;j<QUEUE_SIZE;j++) {
h = myQ->head;
myQ->insert(myQ,k);
printf("inserting %d at position %d, size =%d\n",k--,h, myQ->getSize(myQ));
};
printf("Inserted %d elements\n",myQ->getSize(myQ));
for (j=0;j<QUEUE_SIZE;j++) {
t = myQ->tail;
k = myQ->remove(myQ);
printf("REMOVING %d at position %d, size =%d\n",k,t, myQ->getSize(myQ);
};
printf("Last item removed = %d\n", k);
printf("Current queue size %d\n", myQ->getSize(myQ));
puts("Queue test program");
return EXIT_SUCCESS;
}
子类CachedQueue
CachedQueue.h文件
#ifndef CACHEDQUEUE_H_
#define CACHEDQUEUE_H_
#include "queue.h"
typedef struct CachedQueue CachedQueue;
struct CachedQueue {
Queue* queue; /* base class */
/* new attributes */
char filename[80];
int numberElementsOnDisk;
/* aggregation in subclass */
Queue* outputQueue;
/* inherited virtual functions */
int (*isFull)(CachedQueue* const me);
int (*isEmpty)(CachedQueue* const me);
int (*getSize)(CachedQueue* const me);
void (*insert)(CachedQueue* const me, int k);
int (*remove)(CachedQueue* const me);
/* new virtual functions */
void (*flush)(CachedQueue* const me);
void (*load)(CachedQueue* const me);
};
/* Constructors and destructors:*/
void CachedQueue_Init(CachedQueue* const me, char* fName,
int (*isFullfunction)(CachedQueue* const me),
int (*isEmptyfunction)(CachedQueue* const me),
int (*getSizefunction)(CachedQueue* const me),
void (*insertfunction)(CachedQueue* const me, int k),
int (*removefunction)(CachedQueue* const me),
void (*flushfunction)(CachedQueue* const me),
void (*loadfunction)(CachedQueue* const me));
void CachedQueue_Cleanup(CachedQueue* const me);
/* Operations */
int CachedQueue_isFull(CachedQueue* const me);
int CachedQueue_isEmpty(CachedQueue* const me);
int CachedQueue_getSize(CachedQueue* const me);
void CachedQueue_insert(CachedQueue* const me, int k);
int CachedQueue_remove(CachedQueue* const me);
void CachedQueue_flush(CachedQueue* const me);
void CachedQueue_load(CachedQueue* const me);
CachedQueue * CachedQueue_Create(void);
void CachedQueue_Destroy(Ca CachedQueue* const me);
#endif /*CACHEDQUEUE_H_*/
CachedQueue.c文件
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "cachedQueue.h"
void CachedQueue_Init(CachedQueue* const me, char* fName,
int (*isFullfunction)(CachedQueue* const me),
int (*isEmptyfunction)(CachedQueue* const me),
int (*getSizefunction)(CachedQueue* const me),
void (*insertfunction)(CachedQueue* const me, int k),
int (*removefunction)(CachedQueue* const me),
void (*flushfunction)(CachedQueue* const me),
void (*loadfunction)(CachedQueue* const me)) {
/* initialize base class */
me->queue = Queue_Create(); /* queue member must use its original functions */
/* initialize subclass attributes */
me->numberElementsOnDisk = 0;
strcpy(me->filename, fName);
/* initialize aggregates */
me->outputQueue = Queue_Create();
/* initialize subclass virtual operations ptrs */
me->isFull = isFullfunction;
me->isEmpty = isEmptyfunction;
me->getSize = getSizefunction;
me->insert = insertfunction;
me->remove = removefunction;
me->flush = flushfunction;
me->load = loadfunction;
}
/* operation Cleanup() */
void CachedQueue_Cleanup(CachedQueue* const me) {
Queue_Cleanup(me->queue);
}
/* operation isFull() */
int CachedQueue_isFull(CachedQueue* const me){
return me->queue->isFull(me->queue) &&
me->outputQueue->isFull(me->outputQueue);
}
/* operation isEmpty() */
int CachedQueue_isEmpty(CachedQueue* const me){
return me->queue->isEmpty(me->queue) &&
me->outputQueue->isEmpty(me->outputQueue) &&
(me->numberElementsOnDisk == 0);
}
/* operation getSize() */
int CachedQueue_getSize(CachedQueue* const me) {
return me->queue->getSize(me->queue) +
me->outputQueue->getSize(me->outputQueue) +
me->numberElementsOnDisk;
}
/* operation insert(int) */
// Imsert Algorithm:
// if the queue is full,
// call flush to write out the queue to disk and reset the queue
// end if
// insert the data into the queue
void CachedQueue_insert(CachedQueue* const me, int k) {
if (me->queue->isFull(me->queue)) me->flush(me);
me->queue->insert(me->queue, k);
}
/* operation remove */
// remove algorithm
// if there is data in the outputQueue,
// remove it from the outputQueue
// else if there is data on disk
// call load to bring it into the outputQueue
// remove it from the outputQueue
// else if there is data in the queue
// remove it from there
// (if there is no data to remove then return sentinel value)
int CachedQueue_remove(CachedQueue* const me) {
if (!me->outputQueue->isEmpty(me->outputQueue))
return me->outputQueue->remove(me->outputQueue);
else if (me->numberElementsOnDisk>0) {
me->load(me);
return me->queue->remove(me->queue);
}
else
return me->queue->remove(me->queue);
}
/* operation flush */
// Precondition: this is called only when queue is full
// and filename is valid
// flush algorithm
// if file is not open, then open file
// while not queue->isEmpty()
// queue->remove()
// write data to disk
// numberElementsOnDisk++
// end while
void CachedQueue_flush(CachedQueue* const me){
// write file I/O statements here . . .
}
/* operation load */
// Precondition: this is called only when outputQueue is empty
// and filename is valid
// load algorithm
// while (!outputQueue->isFull() && (numberElementsOnDisk>0)
// read from start of file (i.e., oldest datum)
// numberElementsOnDisk– –;
// outputQueue->insert()
// end while
void CachedQueue_load(CachedQueue* const me) {
// write file I/O statements here . . .
}
CachedQueue * CachedQueue_Create(void) {
CachedQueue* me = (CachedQueue *)
malloc(sizeof(CachedQueue));
if(me!=NULL)
{
CachedQueue_Init(me, "C:\\queuebuffer.dat",
CachedQueue_isFull, CachedQueue_isEmpty, CachedQueue_getSize, CachedQueue_insert, CachedQueue_remove,
CachedQueue_flush, CachedQueue_load);
}
return me;
}
void CachedQueue_Destroy(CachedQueue* const me) {
if(me!=NULL)
{
CachedQueue_Cleanup(me);
}
free(me);
}
好冗长的代码喲,C++轻而易举实现的事情,C却费了好一番周折。也许真的没有必要这么做,但是即便如此,我还是想把这本书看完
不因为别的,就因为想看完