如何使用 std::function 在 C++ 中实现策略模式

How to implement strategy pattern in C++ with std::function

我正在讨论在 C++ 中实现策略模式的最佳方式。到目前为止,我一直使用标准方式,其中上下文有一个指向基本策略 class 的指针,如下所示:

 class AbstractStrategy{
 public:
     virtual void exec() = 0;
 }
 class ConcreteStrategyA{
 public:
     void exec();
 }
 class ConcreteStrategyB{
 public:
     void exec();
 }

 class Context{
 public:
     Context(AbstractStrategy* strategy):strategy_(strategy){}
     ~Context(){
          delete strategy;
       }
      void run(){
           strategy->exec();
      }
 private:
     AbstractStrategy* strategy_;

由于指向对象的指针会导致不良行为,我一直在寻找一种更安全的方法来实现此模式,我发现 其中 std::function 被提议作为处理此问题的更好方法模式。

有人可以更好地解释 std::function 的工作原理吗,也许可以举个策略模式的例子?

请注意,单一方法对象与函数同构,策略只是单一方法对象。

所以基本上,您摆脱了所有 类,而只使用 std::function<void()>

class Context {
public:
    template<typename F>
    explicit Context(F strategy) : strategy(std::move(strategy)) { }

    void run() { strategy(); }

private:
    std::function<void()> strategy;
};

然后你可以将任何可调用对象传递给Context的构造函数:

Context ctx([] { std::cout << "Hello, world!\n"; });
ctx.run();

是这样的吗?

#include <functional>
#include <iostream>


typedef std::function<int(int)> Strategy;

void execute_strategy(Strategy strategy, int object) {
    std::cout << strategy(object) << std::endl;
};

int power2(int i) {
    return i*i;
};

int main() {
    execute_strategy(power2, 3);
}

我的意思是,策略模式是针对没有实际 lambda 的缺点的解决方案。这已经解决了,所以你可以传递适当的功能。

有一些关于这个主题的讨论 here and here. I think it depends on the particular case at hand. Is your strategy a simple function call only, for instance - I often have strategy patterns in which my strategy will need multiple capabilities, which isn't handled well by just having a function or functor. But if you do need just a function or functor, then std::function is a handy way to allow ultimate flexibility, storing function pointers, lambdas or functors. There can be performance issues, which were discussed here 对于原始的 boost 实现。

正在研究 райтфолд 的答案

基本上,您摆脱了所有 类,而只使用 std::function。

此通用函数允许您传递函数、lambda、仿函数和成员函数(使用 std::bind)

class Context {
public:
   explicit Context(std::function<void()> input) : strategy(input) { }

void run() { strategy(); }

private:
   std::function<void()> strategy;
};

然后你可以将任何可调用对象传递给 Context 的构造函数:

Context ctx([] { std::cout << "Hello, world!\n"; });
ctx.run();

void sayHelloWorld(){
   std::cout << "Hello, world!\n";
}


int main(){
   Context ctx( sayHelloWorld );
   ctx.run();  
}

class SayHelloWorld{
   operator()(){std::cout << "Hello, world!\n";}
}

int main(){
   SayHelloWorld hello_world;
   Context ctx( hello_world );
   ctx.run();  
}