程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> Magic C++ (函數指針)(xml配置控件樣式)

Magic C++ (函數指針)(xml配置控件樣式)

編輯:C++入門知識

問題起源:

      我在業余時間編寫基於WTL的控件重繪,為了靈活設置控件的各種樣式,我選擇了使用xml來配置控件的樣式(比如文字顏色,字體,背景顏色)。其中build.xml用來設置控件類型、位置、文字、樣式,skin.xml來設置顏色、字體、圖片。

      首先定義一個類UIData,提供接口LoadCtrl(從build.xml讀取位置信息)和LoadCss(從skin.xml讀取樣式)。

      然後定義一個類ICtrl(繼承UIData)作為控件基類,提供接口Create。

      在IForm中提供一個接口Find

build.xml

<main type="Form" rect="0,0,500,400" css="public">

    <label type="Label" rect="0,0,120,20" text="hello" css="public">

</main>

      ICtrl* Find(const string name);  將name傳入後在Find內部先找出該name對應的type,接著發現該type是Label於是new ILabel,之後再LoadCtrl(該函數最後會調用LoadCss的),最後返回這個ILabel(也可以在返回前調用Create)。

上面是鋪墊,下面是問題:在Find中,傳入一個name讀取對應的type之後,如何只用一步就返回一個new ILabel?

常規做法:

ICtrl* c = nullptr;

if(type == "Label") c = new ILabel;

else if(type == "Button") c= new IButton();

....  return c;  方法可行,只是每次都得做很多次if比較

或者

map<string, ICtrl*> ctrl_;  這個方法不行,根據string返回的只是指針,沒有一個新的對象

So how?C++函數指針閃亮登場,讓我不得不佩服C++ is magic,You can control it all by yourself !


[cpp] 
#pragma once  
#include <iostream>  
#include <string>  
#include <map>  
using namespace std; 
 
class ICtrl 

public: 
    virtual void Print(){   cout<<"ICtrl"<<endl;    } 
}; 
 
class ILabel : public ICtrl 

public: 
    virtual void Print(){   cout<<"ILabel"<<endl;   } 
}; 
 
class IButton : public ICtrl 

public: 
    virtual void Print(){   cout<<"IButton"<<endl;  } 
}; 
 
inline ICtrl* NewLabel(){   return new ILabel();    } 
inline ICtrl* NewButton(){  return new IButton();   } 
 
typedef ICtrl* (*NewCtrl)(); 
 
class CContainer 

private: 
    map<string, NewCtrl> ctrl_; 
public: 
    void Register(const string class_name, NewCtrl method) 
    { 
        ctrl_[class_name] = method; 
    } 
    ICtrl* operator[] (const string class_name) 
    { 
        NewCtrl method = ctrl_[class_name]; 
        return (*method)(); 
    } 
}; 
 
void magic_test() 

    CContainer magic; 
    magic.Register("Label", &NewLabel); 
    magic.Register("Button", &NewButton); 
 
    ICtrl* c = magic["Label"]; 
    c->Print(); 

#pragma once
#include <iostream>
#include <string>
#include <map>
using namespace std;

class ICtrl
{
public:
 virtual void Print(){ cout<<"ICtrl"<<endl; }
};

class ILabel : public ICtrl
{
public:
 virtual void Print(){ cout<<"ILabel"<<endl; }
};

class IButton : public ICtrl
{
public:
 virtual void Print(){ cout<<"IButton"<<endl; }
};

inline ICtrl* NewLabel(){ return new ILabel(); }
inline ICtrl* NewButton(){ return new IButton(); }

typedef ICtrl* (*NewCtrl)();

class CContainer
{
private:
 map<string, NewCtrl> ctrl_;
public:
 void Register(const string class_name, NewCtrl method)
 {
  ctrl_[class_name] = method;
 }
 ICtrl* operator[] (const string class_name)
 {
  NewCtrl method = ctrl_[class_name];
  return (*method)();
 }
};

void magic_test()
{
 CContainer magic;
 magic.Register("Label", &NewLabel);
 magic.Register("Button", &NewButton);

 ICtrl* c = magic["Label"];
 c->Print();
}

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved