//############################################################################
/*
* 多态
*/
// 常见的动态多态
// Non-virtual Interface Idiom (NVI)
struct TreeNode {TreeNode *left, *right;};
class Generic_Parser {
public:
void parse_preorder(TreeNode* node) { //接口不是虚函数
if (node) {
process_node(node);
parse_preorder(node->left);
parse_preorder(node->right);
}
}
private:
virtual void process_node(TreeNode* node) { } //其中处理函数定义成虚函数
};
class EmployeeChart_Parser : public Generic_Parser {
private:
void process_node(TreeNode* node) { //派生类可以定义自己的实现
cout << "Customized process_node() for EmployeeChart.\n";
}
};
int main() {
...
EmployeeChart_Parser ep;
ep.parse_preorder(root);
...
}
// 多态的好处:干净,优雅,通用的代码
/* 满足以下几点
* 1. 基类和派生类之间是is-a关系
* 2. 基类定义一个"通用"的算法,用来给派生类使用
* 3. "通用"算法在派生类中定制
*/
/*
* 虚函数的替换方案
*/
class A {
X x; // 动态地控制执行哪个任务
/* X 可以是:
* 1. 函数指针
* 2. tr1::function, 一个归一化的函数指针
* 3. 策略类
*/
...
};
struct TreeNode {TreeNode *left, *right;};
template <typename T>
class Generic_Parser {
public:
void parse_preorder(TreeNode* node) {
if (node) {
process_node(node);
parse_preorder(node->left);
parse_preorder(node->right);
}
}
void process_node(TreeNode* node) {
static_cast<T*>(this)->process_node(node);
}
};
class EmployeeChart_Parser : public Generic_Parser<EmployeeChart_Parser> {
public:
void process_node(TreeNode* node) {
cout << "Customized process_node() for EmployeeChart.\n";
}
};
int main() {
...
EmployeeChart_Parser ep; //对外界透明,就像是真的多态一样
ep.parse_preorder(root);
...
}
// 用在库编程中比较多,比较看重虚表的开销
// 静态多态,会导致代码量膨胀,每个派生类的基类都是不同的类
// TMP Template Metaprogramming
// 将部分计算开销从运行时提前到编译时
// 也有将模板本身都叫做静态多态的,因为对于不同类型T,像<,=这样的运算符都是不同的