Re: [問題] parameter 是 template function pointer
我剛才解決我的問題了 關於 template和 function pointer的結合
有興趣和耐心的人 可以看一下以下的程式 (ps.很長哦 非常長)
相信有寫過網路程式的人都遇過這問題,我暫用cin 來代表網路收進來的字串
class Device{
void doA(){ .... }
void doB(){ .... }
}
void main(){
Device device;
string messageFromNetwork;
while(true){
cin >> messageFromNetwork; //假設我輸入
if(messageFromNetwork == "a ")
device.doA();
else if(messageFromNetwork == "b")
device.doB();
}
}
我們通常要去用if 來判斷字串的"內容" 來決定呼叫那個函式,那有沒有辨法
不用任何if就可以做到 讓他呼叫想要的函式呢????
以下 我就是要偷懶~我就是不想用if.........
假設 我有2種device
class Device;
class AngelDevice : public Device
class DemonDevice : public Device
-----------------------Device.h----------------------------------
class Device{
public:
Device();
virtual void doAddItem(string parameter);
virtual void doDelItem(string parameter);
virtual void doShowItem(string parameter);
virtual void execute(string command,string parameter)=0;
protected:
int item_number;
};
-----------------------------------------------------------------
----------------------Device.cpp---------------------------------
Device::Device(){
item_number = 0;
}
void Device::doAddItem(string parameter){
int num = atoi(parameter.c_str());
item_number += num;
}
void Device::doDelItem(string parameter){
int num = atoi(parameter.c_str());
item_number -= num;
}
void Device::doShowItem(string parameter){
std::cout << item_number << endl;
}
-----------------------------------------------------------------
一個device有一個屬性叫 item_number代表你有的道具數量
device是一個abstract class 不能被new
doAddItem 則加一個道具
doDelItem 則減一個道具
doShowItem則印出有多少道具
execute等下說明
而有2種device繼承自device 就是AngelDevice , DemonDevice
-----------------------AngelDevice.h-----------------------------
class AngelDevice : public Device{
typedef void (AngelDevice::*APTR)(string);
public:
AngelDevice();
virtual ~AngelDevice();
virtual void doAddItem(string parameter);
virtual void doDelItem(string parameter);
virtual void doTwiceItem(string parameter);
virtual void execute(string command,string parameter);
protected:
Commander<AngelDevice> commander;
};
-----------------------------------------------------------------
----------------------AngelDevice.cpp-----------------------------
AngelDevice::AngelDevice(){
commander.addInvocation("add",&AngelDevice::doAddItem);
commander.addInvocation("del",&AngelDevice::doDelItem);
commander.addInvocation("twice",&AngelDevice::doTwiceItem);
commander.addInvocation("show",&AngelDevice::doShowItem);
}
AngelDevice::~AngelDevice(){
}
void AngelDevice::doAddItem(string parameter){
int num = atoi(parameter.c_str());
item_number += num*2;
}
void AngelDevice::doDelItem(string parameter){
int num = atoi(parameter.c_str());
item_number -= num/2;
}
void AngelDevice::doTwiceItem(string parameter){
item_number*=2;
}
void AngelDevice::execute(string command,string parameter){
APTR ptr = commander.getInvocation(command);
if(ptr)
(this->*ptr)(parameter);
}
---------------------------------------------------------------
AngelDevice 是一種 天使的裝置,如果add item則會得到2倍
del item則只扣除一半,另外還有一個新函式叫
twiceitem 可以讓道具加倍
-------------------------DemonDevice.h------------------------
class DemonDevice : public Device{
typedef void (DemonDevice::*DPTR)(string);
public:
DemonDevice();
virtual ~DemonDevice();
virtual void doAddItem(string parameter);
virtual void doDelItem(string parameter);
virtual void doHalfItem(string parameter);
virtual void execute(string command,string parameter);
protected:
Commander<DemonDevice> commander;
};
---------------------------------------------------------------
--------------------------DemonDevice.cpp----------------------
DemonDevice::DemonDevice(){
commander.addInvocation("add",&DemonDevice::doAddItem);
commander.addInvocation("del",&DemonDevice::doDelItem);
commander.addInvocation("half",&DemonDevice::doHalfItem);
commander.addInvocation("show",&DemonDevice::doShowItem);
}
DemonDevice::~DemonDevice(){
}
void DemonDevice::doAddItem(string parameter){
int num = atoi(parameter.c_str());
item_number += num/2;
}
void DemonDevice::doDelItem(string parameter){
int num = atoi(parameter.c_str());
item_number -= num*2;
}
void DemonDevice::doHalfItem(string parameter){
item_number/=2;
}
void DemonDevice::execute(string command,string parameter){
DPTR ptr = commander.getInvocation(command);
if(ptr)
(this->*ptr)(parameter);
}
-------------------------------------------------------------
demon device是另外一種裝置,add item只能拿到一半
del item則被扣除2倍,另外還有一個half item讓道具減半
按照傳統的做法 你的main應該是長這樣
void main(){
AngelDevice device;
string msgFromNet;
while(true){
cin >> msgFromNet;
string command = msgFromNet.substr(0,msgFromNet.find(" "));
string parameter = msgFromNet.substr(msgFromNet.find(" ")+1);
// if msgFromNet = add 123 then command = add,param = 123
if(command =="add")
device.doAddItem(parameter);
else if(command == "del")
device.doDelItem(parameter);
else if(command == "show")
device.doShowItem(parameter);
else if(command == "twice")
device.doTwiceItem(parameter);
}
}
為了不想看到這個if 所以 我新增了 Commander利用template + function pointer
來解決
----------------------Commander.h------------------------------------
template <typename T>
class Commander{
public:
void addInvocation(string command,void (T::*fptr)(string)){
cmdMap[command] = fptr;
}
void (T::*getInvocation(string command))(string){
return cmdMap[command];
}
protected:
map<string,void (T::*)(string)> cmdMap;
};
----------------------------------------------------------------------
這個是呼應該AngelDevice , DemonDevice 剛才建構子中的
AngelDevice :
commander.addInvocation("add",&AngelDevice::doAddItem);
commander.addInvocation("del",&AngelDevice::doDelItem);
commander.addInvocation("twice",&AngelDevice::doTwiceItem);
commander.addInvocation("show",&AngelDevice::doShowItem);
DemonDevice :
commander.addInvocation("add",&DemonDevice::doAddItem);
commander.addInvocation("del",&DemonDevice::doDelItem);
commander.addInvocation("half",&DemonDevice::doHalfItem);
commander.addInvocation("show",&DemonDevice::doShowItem);
將命令字串和函式做 connect
以後 main 就如以下所示
void main(){
string command,parameter;
AngelDevice device;
while(true){
std::cin >> command >> parameter;
device.execute(command,parameter);
}
}
重點是在 將 string 和 function pointer做結合,並放在map之中
接著 透過 template來完成
需要include : <iostream> <string> <map>
後記 : 在高手如雲的c++版 這也許有點野人獻曝啦
c++真的是方便 透過這樣子做 只需少許class 就可以完成
不像以前用if else 或者 把每個命令都編成class 使用Command Pattern
or Decorate Pattern
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 219.70.172.147
→
08/07 02:23, , 1F
08/07 02:23, 1F
→
08/07 02:41, , 2F
08/07 02:41, 2F
推
08/07 03:02, , 3F
08/07 03:02, 3F
→
08/07 03:03, , 4F
08/07 03:03, 4F
→
08/07 03:04, , 5F
08/07 03:04, 5F
→
08/07 03:06, , 6F
08/07 03:06, 6F
→
08/07 03:06, , 7F
08/07 03:06, 7F
→
08/07 03:06, , 8F
08/07 03:06, 8F
→
08/07 03:07, , 9F
08/07 03:07, 9F
→
08/07 03:08, , 10F
08/07 03:08, 10F
→
08/07 03:08, , 11F
08/07 03:08, 11F
→
08/07 03:10, , 12F
08/07 03:10, 12F
→
08/07 04:24, , 13F
08/07 04:24, 13F
討論串 (同標題文章)
完整討論串 (本文為第 2 之 3 篇):