使用 map<const string, function<? (?)>> 命令解析命令;
Parsing commands using map<const string, function<? (?)>> commands;
问题陈述:
给定交互式输入,对适当的对象(Bank、BankRegister、BasicAccount 等)调用适当的方法。
输入(每条命令单独一行):
create_bank <bank_name>\n
create_customer <bank_number> <customer_name>\n
create_account <bank_number> <customer_number>\n
deposit <amount> <account_number>/<bank_number>\n
etc...
建议解决方案:
#include <functional>
bool create_bank(const string& arguments){
const string& bankName = arguments; //no need to parse here
bankRegister.registerBank(new Bank(bankName,
&bankRegister)); //can't access bankRegister!
return true;
}
int main(){
map<string, function<bool (string)>> commands;
commands.emplace("create_bank",create_bank);
...
BankRegister bankRegister;
string command, arguments;
cin>>command;
getline(cin, arguments);
commands[command](arguments);
...
}
为什么不起作用:
- 无法从函数访问 bankRegister 对象。我可能会通过不断引用函数来传递它,但只有一些函数需要它。我正在考虑将其成员 (m_banks、m_next_bankNumber) 设为静态,但我不得不将它们设为 public,这可能是一个糟糕的设计决定。
- 参数解析应该在哪里进行?这样可以吗?
return值应该代表什么?
a) 参数解析成功
b) 参数解析成功,命令执行成功
我对一些错误使用了例外,但除了 cerr 之外,有些错误是无声的。
我可以在这里使用可变函数来解析参数吗?
- 您还有其他需要改进的地方吗?
在这里使用花哨的代码:
#include <functional>
#include <string>
#include <map>
struct BankRegister {
void create_bank(const std::string& name);
};
void handle_new_bank(BankRegister* reg, const std::string& name) {
reg->create_bank(name);
}
int main() {
std::map<std::string, std::function<void (const std::string)> > cmds;
BankRegister reg;
cmds.emplace("new_bank", std::bind(&handle_new_bank, ®, std::placeholders::_1));
}
您可以更改 create_bank
函数的签名并使用 std::bind
绑定 BankRegister
参数,创建一个调用签名为 bool(const string&)
[= 的函数对象20=]
bool create_bank(const string& arguments, BankRegister& bankRegister){
const string& bankName = arguments; //no need to parse here
bankRegister.registerBank(new Bank(bankName,
&bankRegister));
return true;
}
int main(){
BankRegister bankRegister;
map<string, function<bool (string)>> commands;
using std::placeholders::_1;
commands.emplace("create_bank",std::bind(create_bank, _1, std::ref(bankRegister)));
您可以使用 lambda 函数做同样的事情:
commands.emplace("create_bank", [&bankRegister](const string& args) { return create_bank(args, bankRegister); });
bind
返回的函数对象和 lambda 表达式创建的闭包对象都具有所需的调用签名 bool(const string&)
,但它们还包含对 bankRegister
的引用对象并可以将其传递给 create_bank
问题陈述:
给定交互式输入,对适当的对象(Bank、BankRegister、BasicAccount 等)调用适当的方法。
输入(每条命令单独一行):
create_bank <bank_name>\n
create_customer <bank_number> <customer_name>\n
create_account <bank_number> <customer_number>\n
deposit <amount> <account_number>/<bank_number>\n
etc...
建议解决方案:
#include <functional>
bool create_bank(const string& arguments){
const string& bankName = arguments; //no need to parse here
bankRegister.registerBank(new Bank(bankName,
&bankRegister)); //can't access bankRegister!
return true;
}
int main(){
map<string, function<bool (string)>> commands;
commands.emplace("create_bank",create_bank);
...
BankRegister bankRegister;
string command, arguments;
cin>>command;
getline(cin, arguments);
commands[command](arguments);
...
}
为什么不起作用:
- 无法从函数访问 bankRegister 对象。我可能会通过不断引用函数来传递它,但只有一些函数需要它。我正在考虑将其成员 (m_banks、m_next_bankNumber) 设为静态,但我不得不将它们设为 public,这可能是一个糟糕的设计决定。
- 参数解析应该在哪里进行?这样可以吗?
return值应该代表什么?
a) 参数解析成功
b) 参数解析成功,命令执行成功
我对一些错误使用了例外,但除了 cerr 之外,有些错误是无声的。
我可以在这里使用可变函数来解析参数吗?
- 您还有其他需要改进的地方吗?
在这里使用花哨的代码:
#include <functional>
#include <string>
#include <map>
struct BankRegister {
void create_bank(const std::string& name);
};
void handle_new_bank(BankRegister* reg, const std::string& name) {
reg->create_bank(name);
}
int main() {
std::map<std::string, std::function<void (const std::string)> > cmds;
BankRegister reg;
cmds.emplace("new_bank", std::bind(&handle_new_bank, ®, std::placeholders::_1));
}
您可以更改 create_bank
函数的签名并使用 std::bind
绑定 BankRegister
参数,创建一个调用签名为 bool(const string&)
[= 的函数对象20=]
bool create_bank(const string& arguments, BankRegister& bankRegister){
const string& bankName = arguments; //no need to parse here
bankRegister.registerBank(new Bank(bankName,
&bankRegister));
return true;
}
int main(){
BankRegister bankRegister;
map<string, function<bool (string)>> commands;
using std::placeholders::_1;
commands.emplace("create_bank",std::bind(create_bank, _1, std::ref(bankRegister)));
您可以使用 lambda 函数做同样的事情:
commands.emplace("create_bank", [&bankRegister](const string& args) { return create_bank(args, bankRegister); });
bind
返回的函数对象和 lambda 表达式创建的闭包对象都具有所需的调用签名 bool(const string&)
,但它们还包含对 bankRegister
的引用对象并可以将其传递给 create_bank