假设我有一个类,它实现了许多类似的方法,相同的返回类型和相同的参数类型,以保持简单。
部首:
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);
}
非常相似的方法,但只是方法名称中的方向(在本例中为Forward和Right)以及其中一个内部函数的名称不同。
在这里抽象通用通用结构的最佳方法是什么?
答案 0 :(得分:3)
您可以通过多种方式进行此操作,我个人使用了与以下类似的方法:
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();
}
答案 1 :(得分:2)
说实话,你不应该在这个级别的算法上进行概括。你只需要一个向量并用常量来缩放它。如果你正在做一些更复杂的事情,那么这将是另一个故事。我的首要建议就是让它保持这种状态。
其次,如果你坚持在这里推广它(我假设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);
}
};
我更喜欢您的原始代码。
答案 2 :(得分:1)
您可以使用tag-dispatching。
使用相同的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() );
如果要创建更多方向,则只需要一个实现静态成员函数的新标记类。
答案 3 :(得分:0)
当您处理不同的值(向前,向右)时,不打算使用模板,它们意味着处理不同的类型(int,double)。 您可以使用一个带参数的通用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);
}