最直接的学习方式就是RTFSC
假设我需要编写库接口 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; }
最后, 这个过程还可以重复的! C 重载 B , B 重载 A . 没有问题.
假设我们有个工厂类 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子类需要修改的文件也少了 , 也不容易遗漏了 .
还是用上面的例子, 每次添加一个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 } }