简体   繁体   English

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

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

Let's say I have a class which implements any number of similar methods, same return type and same parameter type to keep it simple. 假设我有一个类,该类实现许多相似的方法,相同的返回类型和相同的参数类型,以使其简单。

Header: 标头:

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

Implementation: 实现方式:

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

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

Very similar methods, but only differing by the direction (Forward and Right in this case) in the method name, and the name of one of the internal functions. 非常相似的方法,只是方法名称和内部函数之一的名称不同(在这种情况下为“向前”和“向右”)。

What is the best way to abstract the common generic structure here? 在这里抽象通用泛型结构的最佳方法是什么?

You can do it in multiple ways, personally I've used an approach similar to the following: 您可以通过多种方式进行操作,就我个人而言,我使用的方法类似于以下内容:

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 { ... }

Of course you can do the same exact thing without templates but I guess that you know what you are doing if you are specifically needing them. 当然,不用模板也可以做同样的事情,但是我想如果您特别需要它们,您就会知道自己在做什么。

Mind that you could directly pass the function as a template argument but I found it less clear, something like: 请注意,您可以直接将函数作为模板参数传递,但我发现它不太清楚,例如:

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

To be honest you should not generalize at this level of algorithm. 老实说,您不应该对此算法进行概括。 You just get a vector and scale it with a constant. 您只需要得到一个向量,并用一个常数对其进行缩放。 If you were doing something more complex, then it would be another story. 如果您正在做更复杂的事情,那将是另一回事了。 My first and foremost suggestion is let it stay this way. 我的首要建议是让它保持这种状态。

Second, if you insist on generalization here it is (I assume GetXVector methods are class member): 其次,如果您坚持在这里进行通用化(我假设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);
    }
};

I prefer your original code. 我更喜欢您的原始代码。

You could use tag-dispatching. 您可以使用标记分派。

Create the tag classes with same static member functions which implement the specific behavior: 使用实现特定行为的相同static成员函数创建标签类:

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

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

In your class, implement a template move function which takes an instance of the Direction class, but doesn't use it. 在您的类中,实现一个模板move函数,该函数接受Direction类的一个实例,但不使用它。 Instead it calls the static member function of the tag class. 而是调用标记类的static成员函数。

class MyCharacter
{
public:

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

Usage example: 用法示例:

MyCharacter mc;

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

If you want to create more directions, only a new tag class is needed which implements the static member function. 如果要创建更多方向,则只需一个新的标记类即可实现静态成员函数。

Templates are not meant to be used when you handle different values (forward, right), they meant to handle different types (int, double). 当您处理不同的值(向前,向右)时,不打算使用模板,而是要处理不同的类型(int,double)。 You can use one generic Move function with arguments: 您可以使用一个带有参数的通用Move函数:

void Move(int x, int y);

// Move forward
Move (0, 1);

// Move right
Move (1, 0);

You can use function pointers to combine move direction and corresponding function in a struct: 您可以使用函数指针在结构中组合移动方向和相应的函数:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 C ++ - 为什么静态字符串在由不同函数引用时会给出稍微不同的地址? - C++ - Why does a static string give slightly different addresses when referred to by different functions? C++ 将源文件中的某些功能设为私有的最佳方法是什么? - C++ what's the best way to make some functions inside source file private? C++ 实现具有不同优先级功能的优先级队列的最佳方法是什么? - C++ What's the best way to implement a Priority Queue with varying priority functions? 在C ++中进行实验时,测量某些函数的cpu时间的最佳方法是什么? - What is the best way to measure the cpu time of some functions when doing experiments in C++? 在 C++ 中使用 HashMap 的最佳方法是什么? - What is the best way to use a HashMap in C++? 分发C ++类的最佳方法是什么 - What is the best way to distribute C++ class 用C ++存储表的最佳方法是什么 - What is the best way to store a table in C++ 在C ++中附加数据的最佳方法是什么 - What is the best way to append data in C++ 在 C++ 中组织标题的最佳方法是什么? - What is the best way to organize headers in C++? 用 Qt/C++ 中的一个代码构建两个略有不同的项目 - Build two slightly different projects from one code in Qt/C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM