C++中的策略模式和协变返回类型

问题描述

class Context{
public:
    Strategy* strategy;
    void PickStrategy(Strategy *strategy){
        delete this->strategy;
        this->strategy = strategy;
    }

    C* execute(string some_text) const{
        return this->strategy->execute(std::move(some_text));
    }
};
class C{

};

class D: public C{

}
class MyStrategy: public Strategy{
    D* execute(string some_text){
        // business logic
        return pointer_to_D;
    }
}

客户端:

auto context = Context();
context.PickStrategy(new MyStrategy());
auto output1 = context.execute("some_text");
auto output2 = context.execute("some_text2");
if (output1 == output2){
    // business logic
}
bool operator==(const D& d1,const D& d2){
    // business logic
}

我有一个应用程序,我认为采用策略模式会很有意义。所以我决定使用它。但我的问题是,在根本不涉及客户端的情况下,我是否可以使用我的重载运算符,该运算符是专门针对特定产品确定的,该特定产品应该由上下文选择的策略返回。如您所知,我们可以在 C++ 中的虚拟覆盖函数实现中返回派生类对象,这称为协变返回类型,但在这种情况下,自动引用假定层次结构中最通用的类​​型,这导致无法按预期使用重载运算符,尽管我希望它在运行时根据上下文中选择的策略进行更改,而不必费心进行任何额外的令人讨厌的单片 dynamic_cast 检查,因为如果我这样做,结果证明使用策略模式是没有意义的.那么,在我的情况下,如何通过上下文对象使用协变返回类型?

解决方法

这是一个长期存在的问题。核心问题是,Context 希望对其策略(包括其返回值的动态类型)进行动态控制,但其用户希望对该返回值进行静态保证。您可以在策略和/或返回类型上模板 Context,并可能在返回类型上模板 Strategy,但从根本上说,您需要在编译时引入对返回类型的限制或您需要在运行时进行不安全的转换。