输入1个命令就可以执行某个操作(有点像回到了dos的时代了 呵呵~)
有人会想 不如直接实现1个GUI
但是要实现1个GUI可能会比实现1个控制台要难得多
有时在功能上和速度上都不如控制台
1个控制台
首先要能把信息(就是1大堆字符串)显示出来
最简单的方法就是用cout输出
也可以就直接从窗口中显示
但是每个人实现的方法都不同
我也不能硬性规定什么(如果这个搞得不好就会增加耦合性)
所以我把这部分的内容写成1个接口函数
void PrintLog( const std::string& str, unsigned long LogLevel );
参数是1个字符串和1个LogLevel
LogLevel 的作用就是比较这个字符串的重要程度
可能是错误信息哟~
这样就可以用不同的方发来显示信息
至于怎样显示
就留给读者去干了
接着就是输入的命令
当然是用字符串
但是我们同常都是1个个字符输入(废话=。=)
但是程序内部调用就可以直接用字符串啦
所以这里就要实现两个函数了
void InputCommand( const std::string & strCommand );
void InputCommand( char Command );
最后就是执行命令
怎样执行??
当然是某个调用函数啦
但首先就是要把函数和命令加载到1个容器里
这个容器最好是用hash_map
好处就是寻找是速度快
缺点就是插入时慢
我们需要的就是执行命令是要快
而插入通常都是在程序开始时进行的
另1个问题来了
调用函数是普通的函数就容易
但调用的是成员函数就嘛烦多了
有人会想可以继承1个虚基类啊
然后把所有要调用成员函数的类都继承这个虚基类
但是这样做是不是有点难看啊
但是又放弃了普通的函数
难道又继承这个虚基类 然后在实现时调用这个普通函数
但是有的类是不能改动的或是已经写好的呢?
用这个方法也可以做到
但只能用1个字来形容 就是"烦"
但是有没有更好的方法呢??
当然有
如果各位有看我上1篇文章的话就会觉得这1切都变得无比得简单了
上1编文章说的是"委托"
其实就是1个范化仿函数
其他1些库都有这个东西
但我用的是我的方法
当然是简单的方法啦^_^
容器就是这样子了hash_map< std::string, Delegate>
仿函数的参数当然可以自行设定
而我设定的参数是(const std::string&, std::string& )
返回值是unsigned long 是信息的类型(例如错误信息)
第1个参数是输入的是命令
我们在敲打键盘输入命令时都会在后面加几个参数之类的
然后就可以在被调用的函数种处理
第2个是返回的信息
可以立即的显示出来
仿函数就是这样子了Delegate<unsigned long, const std::string&, std::string& >
先来1段代码
template
<
class Functor
>
class FunctorManager
{
public:
typedef Functor Functor;
public:
bool RegisterFunctor(const std::string & strName, Functor& function)
{
return m_Functor_List.insert(
std::make_pair(strName, function)).second;
}
bool UnregisterFunctor(const std::string & strFunctorName )
{
return m_Functor_List.erase(strFunctorName) == 1;
}
Functor* ActivationFunctor( const std::string & strFunctorName )
{
Functor_List_Iterator_t i = m_Functor_List.find(strFunctorName);
if (i == m_Functor_List.end())
{
return 0;
}
return &((*i).second);
}
protected:
typedef std::hash_map< std::string, Functor> Functor_List_t;
typedef typename std::hash_map< std::string,Functor>::iterator Functor_List_Iterator_t;
Functor_List_t m_Functor_List;
};
看名字就是到管理仿函数的class 是1个base class
template
<
class PrintPolicy
>
class Console : public FunctorManager<
Delegate
<
unsigned long,
const std::string&,
std::string&
>
>
{
public:
typedef Console<PrintPolicy> MyType;
typedef PrintPolicy PrintType;
typedef Delegate
<
unsigned long,
const std::string&,
std::string&
> Function_t;
enum
{
CONSOLE_LOG_LEVEL_INFORMATION,
CONSOLE_LOG_LEVEL_COMMAND,
CONSOLE_LOG_LEVEL_WARNING,
CONSOLE_LOG_LEVEL_ERROR
};
public:
//构造函数 CommandSign 是命令也要有个表记吧
// 还用先注册自己1个成员函数 输出所有命令的名称
Console(char CommandSign = '/')
:m_CommandSign(CommandSign)
{
Function_t __PrintAllCommand(this,Console::PrintAllCommand);
bool b = RegisterFunctor( "Print All Command", __PrintAllCommand);
assert(b);
}
~Console(){}
public:
//输入命令
void InputCommand( const std::string & strCommand )
{
//把this转换成派生类的this
//这样就可以不用设成虚函数就可以调用派生类的函数
PrintPolicy* pT = static_cast<PrintPolicy*>(this);
//命令是否为空
if(strCommand.empty())
{
return;
}
//命令的第1个字符是否"/"
if( strCommand[0] != m_CommandSign )
{
pT->PrintLog( strCommand,CONSOLE_LOG_LEVEL_WARNING );
return;
}
pT->PrintLog(strCommand, CONSOLE_LOG_LEVEL_COMMAND);
//把命令和参数分开
std::string::size_type next_space = strCommand.find(' ');
std::string CommandHead = strCommand.substr(1, next_space-1-1);
//执行命令调用的函数
Function_t* pfun = ActivationFunctor(strCommand);
if (pfun)
{
std::string OutLog;
unsigned long LogLevel = (*pfun)(strCommand,OutLog);
pT->PrintLog( OutLog, LogLevel );
}
else
{
pT->PrintLog("Have no this Command ",CONSOLE_LOG_LEVEL_WARNING);
}
}
protected:
//把所以的命令的名称都打印出来
unsigned long PrintAllCommand( const std::string& in, std::string& out)
{
assert( in == "Print All Command" );
Functor_List_Iterator_t i = m_Functor_List.begin();
Functor_List_Iterator_t iend = m_Functor_List.end();
for(; i != iend; ++i)
{
static_cast<PrintPolicy*>(this)->PrintLog( (*i).first, CONSOLE_LOG_LEVEL_INFORMATION );
}
out = "Print All Command Complete .";
return CONSOLE_LOG_LEVEL_INFORMATION;
}
private:
const char m_CommandSign;//命令的表记
};
实现的代码是不是很简单 呵呵~这就是全靠STL和我的范化仿函数了
(有时真不感想象没有STL的日子会是怎样过=.=)
用发很简单
继承这个class 然后实现PrintLog就可以了
class MyConsole : public Console<MyConsole>
{
void PrintLog( const std::string& str, unsigned long LogLevel )
{
... ...
}
};
全文完