最直接的学习方式就是RTFSC
1. OOC 之 OVERRIDE --- 使用函数指针实现重载和代码重用机制.
假设我需要编写库接口 do_something 但是我只能明确这个接口的通用功能, 可能不同
工程会有些自己的定制需求. 于是我就这样实现:
void (*do_something)(void);
void do_something_default(void)
{
// Lots of common job
}
do_something = do_something_default;
这样如果用户不需要特殊定制, 就直接调用这个接口
do_something();
如果他需要特殊定制的话, 就向下面这个操作:
void (*original_do) (void) = NULL;
void do_special_job(void)
{
original_do();
//Special jobs
// ...
}
void func_hook()
{
if(!original_do)
{
original_do = do_something;
}
do_something = do_special_job;
}
然后在使用 do_something 之前先调用 HOOK 函数 func_hook , 就成功的重载了,而且之前的代码也很好的复用了 .
最后, 这个过程还可以重复的! C 重载 B , B 重载 A . 没有问题.
2. 使用构造函数实现添加链表节点 , 实现自由定制工厂类
假设我们有个工厂类 Factory, 可以生产各种 Item 类的子类, 但是我们不知道 Item 类到底会有多少子类 , 于是我们让 Factory 维护一个链表,
每个节点上有一个生产Item 特定子类类的接口.每一个Item子类都自己设计自己的节点 . 这样Factory 只需要每次遍历链表,根据参数选出对
应的节点来生产Item子类就可以了.
问题是我不希望在main函数中开始专门加入一个 init_list 来一一添加所有的Item子类的节点 ,这样容易遗漏 , 而且每次添加新的Item子类都
要来修改这个接口, 我希望新的Item 子类自行将生产节点添加到链表中 !
例子:
// Factory.h
struct Node
{
Node( Item*(*f)() , Node * n) : Item_creator(f) , next(n) {}
Item * (* Item_creator)();
Node * next;
};
class Factory
{
public :
static void addNode( Node *);
private :
static Node * head;
};
class ListAddr
{
public:
ListAddr(Node *n){ Factory::addNode(n);}
};
//Item.h
class Item
{
// ...
};
class A : public Item
{
public:
Item * A_creator();
// ...
};
// item.cpp
Node A_Node( A::A_creator , 0 );
ListAddr A_adder(&A_Node);
这样在main函数开始之前, 链表就已经构造好了, main函数不需要在考虑它了.
而且添加Item子类需要修改的文件也少了 , 也不容易遗漏了 .
3. 使用宏来减少重复工作 .
还是用上面的例子, 每次添加一个Item 子类 , 都需要定义他的Node 和 ListAddr , 这是很烦人的. 下面的宏可以节约时间
#define NODEADDER(class_name, func ) \
Node class_name_##node(func,0);\
ListAddr class_name##adder(&class_name_##node);
添加子类节点的时候:
NODEADDER(A, A::A_creator)
是不是简洁了很多!
4. 使用函数调用实现继承和派生的和谐存在
C++为我们提供了继承和派生, 但是如果我想要在原有的基础上添加新的操作呢 ?
简单的实现是这样的:
class Father
{
public:
virtual void InterfaceA()
{
//TODO :
}
};
class Child : public Father
{
public:
virtual void InterfaceA()
{
Father::InterfaceA();
//TODO : somethine else
}
}
这样子每一个子类都要写
Father::InterfaceA();
为了减少这部分工作量, 也减少忘记写导致BUG的可能性, 可以这样
class Father
{
public:
void InterfaceA()
{
// TODO Common stuff
SelfInterfaceA();
}
virtual void SelfInterfaceA() = 0;
};
class Child : public Father
{
public:
vitrual void SelfInterfaceA()
{
//TODO : somethine else
}
}