C++進階--靜態多型
阿新 • • 發佈:2018-12-25
//############################################################################ /* * 多型 */ // 常見的動態多型 // 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,像<,=這樣的運算子都是不同的