简体   繁体   English

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

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

Below is a simple strategy pattern implemented using the base class references to a derived object.下面是一个简单的策略模式,使用基础 class 引用对派生的 object 的引用。 The solution does not produce an expected result (12 and 2).该解决方案不会产生预期的结果(12 和 2)。 When base class reference is switched to pointers, it works.当基本 class 参考切换到指针时,它可以工作。 Can someone explain what is happening behind the scenes with references here?有人可以用这里的参考资料解释幕后发生的事情吗? The issue is in the setStrategy() method of the Context class.问题出在上下文 class 的 setStrategy() 方法中。 I am wondering why doesn't the strategy variable reference the ConcreteStrategy2 after the call to setStrategy() method?我想知道为什么在调用 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;
}

You are trying to reassign a reference, but references cannot be reassigned.您正在尝试重新分配参考,但无法重新分配参考。 It assigns to Strategy object being referred to instead.它分配给被引用的Strategy object。 If you make Strategy non-copyable/assignable that re-assignment through reference will fail to compile.如果您使Strategy不可复制/可分配,则通过引用重新分配将无法编译。

Use a pointer instead:改用指针:

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

Using reference members is almost always a mistake because it breaks value semantics, as you observe.正如您所观察到的,使用引用成员几乎总是一个错误,因为它破坏了值语义。 One can get away with using reference members in non-copyable classes.在不可复制的类中使用引用成员可以逃脱惩罚。

Additional solution to Maxim Egorushkins answer. Maxim Egorushkins 答案的附加解决方案。

You could also use std::reference_wrapper instead of a pointer:您还可以使用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; }
};

Here are both versions next to each other: https://gcc.godbolt.org/z/dveK9T这是两个版本并排的:https://gcc.godbolt.org/z/dveK9T

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

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