[英]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.