繁体   English   中英

基本 class 参考派生 object - 策略模式

[英]base class reference to derived object - strategy pattern

下面是一个简单的策略模式,使用基础 class 引用对派生的 object 的引用。 该解决方案不会产生预期的结果(12 和 2)。 当基本 class 参考切换到指针时,它可以工作。 有人可以用这里的参考资料解释幕后发生的事情吗? 问题出在上下文 class 的 setStrategy() 方法中。 我想知道为什么在调用 setStrategy() 方法后策略变量不引用 ConcreteStrategy2 ?

#include <iostream>


class Strategy {
public:
    virtual ~Strategy() = default;

    virtual int execute(int x, int y) const = 0;
};


class ConcreteStrategy1 : public Strategy {
public:
    int execute(int x, int y) const override
    {
        return x + y;
    }
};


class ConcreteStrategy2 : public Strategy {
public:
    int execute(int x, int y) const override
    {
        return x - y;
    }
};


class Context {
    Strategy &strategy;

public:
    Context(Strategy &strategy) : strategy {strategy}
    {
    }

    void setStrategy(Strategy &strat)
    {
        this->strategy = strat;
    }

    void doLogic() const
    {
        std::cout << strategy.execute(7, 5) << std::endl;
    }
};

int main()
{
    ConcreteStrategy1 strat;
    Context context {strat};
    context.doLogic();

    ConcreteStrategy2 strat2;
    context.setStrategy(strat2);
    context.doLogic();

    return 0;
}

您正在尝试重新分配参考,但无法重新分配参考。 它分配给被引用的Strategy object。 如果您使Strategy不可复制/可分配,则通过引用重新分配将无法编译。

改用指针:

class Context {
    Strategy* strategy;
public:
    Context(Strategy &strategy) : strategy {&strategy} {}
    void setStrategy(Strategy &strat) { this->strategy = &strat; }
    void doLogic() const { std::cout << strategy->execute(7, 5) << std::endl; }
};

正如您所观察到的,使用引用成员几乎总是一个错误,因为它破坏了值语义。 在不可复制的类中使用引用成员可以逃脱惩罚。

Maxim Egorushkins 答案的附加解决方案。

您还可以使用std::reference_wrapper代替指针:

class Context {
    std::reference_wrapper<Strategy> strategy;

public:
    Context(Strategy &strategy) : strategy {strategy} { }
    void setStrategy(Strategy &strat) { this->strategy = strat; }
    void doLogic() const { std::cout << strategy.get().execute(7, 5) << std::endl; }
};

这是两个版本并排的:https://gcc.godbolt.org/z/dveK9T

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM