扩展通用功能

时间:2015-03-03 19:44:58

标签: c++ design-patterns enums

我正在创造一个游戏,在这个游戏中,球可以以各种方式被捕获,这些都会导致不同的行为。最初,我想在接球时为某个通用方法添加一个枚举,然后将球委托以某种方式抓住球时发生的动作。一个例子是:

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);

然而,我的主要问题是,这根本不可扩展,这是我实际上希望用这种通用方法实现的。如果我将方法设为枚举,我不能简单地扩展枚举并覆盖Catch的派生类中的虚拟Weapon方法。如果我决定在某个派生类中扩展该方法,我必须创建一个新的枚举,它从Method枚举的最后一个值开始。我不认为这是处理这种情况的正确方法,但我不知道这种情况下的最佳做法是什么。它可能涉及模板专业化吗?对我来说,主要的问题是我不能简单地扩展枚举。

2 个答案:

答案 0 :(得分:3)

您可以使用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));

答案 1 :(得分:1)

这有点不明显,因为我不确定你的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);

如果没有您在问题中没有显示的周围代码或类似的先决条件,我认为没有任何背面,并且声明执行类似操作的新功能完全是分散的和可扩展的。< / p>

如果你需要通过其他函数传递CatchMethod,你可以简单地传递一个函数指针。

顺便说一句,顺便说一句,除非WeaponCharacter这里有typedef到其他东西,否则按值传递这些东西通常是个坏主意。您可能想要使用引用或指针。