扩展通用功能
Extending a general purpose function
我正在创建一个游戏,在这个游戏中,可以用多种方式接球,这都会导致不同的行为。最初,我想在接球时向某个通用方法添加一个枚举,然后它将委托以某种方式接住球时发生的动作。一个例子是:
void Weapon::Catch(Character Catcher, CatchMethod Method)
{
switch (Method)
{
case Method::PickUp: OnPickup(Catcher); break;
case Method::Pass: OnPass(Catcher); break;
// etc
}
}
这将允许我将函数调用为:
MyWeapon->Catch(Catcher, Method::Pickup);
MyWeapon->Catch(Catcher, Method::Pass);
之类的。我认为这比
读起来更好
MyWeapon->CatchByPickup(Catcher);
MyWeapon->CatchByPass(Catcher);
然而,我的主要问题是,这根本不可扩展,而这正是我实际上希望通过这种通用方法实现的。如果我将方法设为枚举,我不能简单地扩展枚举并覆盖 Weapon
的派生 class 中的虚拟 Catch
方法。如果我决定在某些派生的 class 中扩展该方法,我必须创建一个从 Method
枚举的最后一个值开始的新枚举。我不认为这是处理这种情况的正确方法,但我不知道在这种情况下最好的做法是什么。它可能涉及模板专业化吗?我的主要问题是我不能简单地扩展枚举。
这有点不明显,因为我不确定您的 Catch
方法中是否有与系统相关的任何其他代码,但在我看来您可能不想这样做完全使用方法并反转控件以具有不同的功能。像这样,例如:
void pickup(Weapon weapon, Character catcher) {
/* Do whatever your OnPickup does */
}
void pass(Weapon weapon, Character catcher) {
/* Do whatever your OnPass does */
}
然后,显然,就这样称呼它们:
pickup(MyWeapon, Catcher);
pass(MyWeapon, Catcher);
如果没有你在问题中没有显示的周围代码或类似的先决条件,我认为这没有任何反面,并且声明新功能来做类似的事情是完全去中心化和可扩展的.
如果您需要通过其他函数传递CatchMethod
,您可以直接传递一个函数指针。
顺便说一句,除非这里的 Weapon
和 Character
是其他东西的类型定义,否则按值传递这些东西通常不是一个好主意。您可能想改用引用或指针。
您可以使用 std::function
。
using CatchMethod = std::function<void(Character)>;
void Weapon::Catch(Character Catcher, CatchMethod Method)
{
Method(Catcher);
}
调用该函数非常简单
// If its a regular function you can just use the pointer to the function
weapon.Catch(Player, &OnPickup);
// If its a member function you can use lambda
weapon.Catch(Player, [this](Character Catcher){OnPickup(Catcher);});
// or std::bind (slightly more verbose and less flexible)
weapon.Catch(Player, std::bind(&Weapon::OnPickup, this, std::placeholders::_1));
我正在创建一个游戏,在这个游戏中,可以用多种方式接球,这都会导致不同的行为。最初,我想在接球时向某个通用方法添加一个枚举,然后它将委托以某种方式接住球时发生的动作。一个例子是:
void Weapon::Catch(Character Catcher, CatchMethod Method)
{
switch (Method)
{
case Method::PickUp: OnPickup(Catcher); break;
case Method::Pass: OnPass(Catcher); break;
// etc
}
}
这将允许我将函数调用为:
MyWeapon->Catch(Catcher, Method::Pickup);
MyWeapon->Catch(Catcher, Method::Pass);
之类的。我认为这比
读起来更好MyWeapon->CatchByPickup(Catcher);
MyWeapon->CatchByPass(Catcher);
然而,我的主要问题是,这根本不可扩展,而这正是我实际上希望通过这种通用方法实现的。如果我将方法设为枚举,我不能简单地扩展枚举并覆盖 Weapon
的派生 class 中的虚拟 Catch
方法。如果我决定在某些派生的 class 中扩展该方法,我必须创建一个从 Method
枚举的最后一个值开始的新枚举。我不认为这是处理这种情况的正确方法,但我不知道在这种情况下最好的做法是什么。它可能涉及模板专业化吗?我的主要问题是我不能简单地扩展枚举。
这有点不明显,因为我不确定您的 Catch
方法中是否有与系统相关的任何其他代码,但在我看来您可能不想这样做完全使用方法并反转控件以具有不同的功能。像这样,例如:
void pickup(Weapon weapon, Character catcher) {
/* Do whatever your OnPickup does */
}
void pass(Weapon weapon, Character catcher) {
/* Do whatever your OnPass does */
}
然后,显然,就这样称呼它们:
pickup(MyWeapon, Catcher);
pass(MyWeapon, Catcher);
如果没有你在问题中没有显示的周围代码或类似的先决条件,我认为这没有任何反面,并且声明新功能来做类似的事情是完全去中心化和可扩展的.
如果您需要通过其他函数传递CatchMethod
,您可以直接传递一个函数指针。
顺便说一句,除非这里的 Weapon
和 Character
是其他东西的类型定义,否则按值传递这些东西通常不是一个好主意。您可能想改用引用或指针。
您可以使用 std::function
。
using CatchMethod = std::function<void(Character)>;
void Weapon::Catch(Character Catcher, CatchMethod Method)
{
Method(Catcher);
}
调用该函数非常简单
// If its a regular function you can just use the pointer to the function
weapon.Catch(Player, &OnPickup);
// If its a member function you can use lambda
weapon.Catch(Player, [this](Character Catcher){OnPickup(Catcher);});
// or std::bind (slightly more verbose and less flexible)
weapon.Catch(Player, std::bind(&Weapon::OnPickup, this, std::placeholders::_1));