在 c++ 中抽象两个略有不同的函数的最佳方法是什么?

What is the best way to abstract two slightly different functions in c++?

本文关键字:函数 最佳 是什么 方法 抽象 c++ 两个      更新时间:2023-10-16

假设我有一个类,它实现了任意数量的类似方法,相同的返回类型和相同的参数类型以保持简单。

页眉:

protected:
void MoveForward(float Magnitude);
void MoveRight(float Magnitude);

实现:

void MyCharacter::MoveForward(float Magnitude) {
AddMovementInput(GetActorForwardVector() * Magnitude);
}
void Myharacter::MoveRight(float Magnitude) {
AddMovementInput(GetActorRightVector() * Magnitude);
}

非常相似的方法,但仅在方法名称的方向(在本例中为向前和向右(以及其中一个内部函数的名称上有所不同。

在这里抽象通用结构的最佳方法是什么?

您可以通过多种方式做到这一点,我个人使用了一种类似于以下内容的方法:

enum class Direction { LEFT, RIGHT, TOP, BOTTOM };
class MyCharacter {
template<Direction DIR> Vector MyCharacter::getVector() const;
template<Direction DIR> void move() {
AddMovementInput(getVector<Dir>() * magnitude);
}
}
template<> Vector MyCharacter::getVector<Direction::LEFT>() const { ... }
template<> Vector MyCharacter::getVector<Direction::RIGHT>() const { ... }

当然,您可以在没有模板的情况下做同样的事情,但我想如果您特别需要它们,您知道自己在做什么。

请注意,您可以直接将该函数作为模板参数传递,但我发现它不太清楚,如下所示:

float GetActorForwardVector() { return 3.0f; }
class Foo
{
public:
template<float (*F)()> float move() { return F(); }
inline float moveLeft() { return move<GetActorForwardVector>(); }
};
int main()
{
Foo foo;
std::cout << foo.moveLeft();
}

老实说,你不应该在这个算法级别进行概括。你只需得到一个向量并用常量缩放它。如果你正在做一些更复杂的事情,那将是另一回事。我的第一个也是最重要的建议是让它保持这种状态。

其次,如果你坚持在这里泛化,它是(我假设GetXVector方法是类成员(:

class Foo
{
protected: 
void MoveForward(float x) { Move(&Foo::GetActorForwardVector, x); }
void MoveRight(float x) { Move(&Foo::GetActorRightVector, x); }
private:
template<typename GetDirectionFunc>
void Move(GetDirectionFunc getDirection, float x)
{
AddMovementInput((this->*getDirection)() * x);
}
};

我更喜欢你的原始代码。

您可以使用标记调度。

使用实现特定行为的相同static成员函数创建标记类:

namespace Direction {
struct Forward
{
static Vector actorVector() { return GetActorForwardVector(); }
};
struct Right
{
static Vector actorVector() { return GetActorRightVector(); }
};
} // namespace Direction

在您的类中,实现一个模板move函数,该函数采用 Direction 类的实例,但不使用它。相反,它调用标记类的static成员函数。

class MyCharacter
{
public:
template< typename Direction >
void move( const float magnitude, const Direction )
{
AddMovementInput( Direction::actorVector() * magnitude );
}
};

使用示例:

MyCharacter mc;
mc.move( 10.0, Direction::Forward() );

如果要创建更多方向,则只需要一个新的标记类来实现静态成员函数。

模板不是用来处理不同值(向前、向右(的,它们意味着处理不同的类型(整数、双精度(。 您可以将一个通用 Move 函数与参数一起使用:

void Move(int x, int y);
// Move forward
Move (0, 1);
// Move right
Move (1, 0);

可以使用函数指针在结构中组合移动方向和相应的函数:

struct MOVE_INFO
{
int x;
int y;
void (*GetVector)(void);
}
void Move(MOVE_INFO mv)
{
...
mv.GetVector();
...
}
main()
{
MOVE_INFO forward = {0, 1, SomeLib::GetForwardVector};
MOVE_INFO right = {1, 0, SomeLib::GetRightVector};
// Move Forward
Move(forward);
// Move Right
Move(right);
}
相关文章: