本书Strategy Pattern中的Head First Design Patterns示例是用C++在[here]编写的。我正在尝试根据Effective GoF Patterns with C++11 and Boost将其转换为C++ 11样式,如下所示。
Quack 行为:
struct Quack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct MuteQuack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
Fly 行为:
struct FlyWithWings {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct FlyNoWay {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
Duck 层次结构:
class Duck
{
public:
typedef std::function<void(void)> QUACK;
typedef std::function<void(void)> FLY;
public:
Duck(const QUACK &q, const FLY &f)
: m_Quack(q), m_Fly(f) {}
virtual ~Duck()
{
}
void perform_quack()
{
m_Quack();
}
void perform_fly()
{
m_Fly();
}
protected:
QUACK m_Quack;
FLY m_Fly;
private:
Duck(const Duck&) = delete;
Duck& operator=(const Duck&) = delete;
};
class MallardDuck
: public Duck
{
public:
MallardDuck()
: Duck(&Quack::quack, &FlyWithWings::fly)
{
}
};
class PaintedDuck
: public Duck
{
public:
PaintedDuck()
: Duck(&MuteQuack::quack, &FlyNoWay::fly)
{
}
};
到目前为止,客户工作良好。
int main()
{
MallardDuck x1;
x1.perform_quack();
x1.perform_fly();
PaintedDuck x2;
x2.perform_quack();
x2.perform_fly();
return 0;
}
现在,我想将一个新的类
RubberDuck
扩展到鸭层次结构,并且RubberDuck
使用具有对象状态的新的飞行行为FlyWithRocket
。如下:一种新的 Fly 行为:
class FlyWithRocket {
public:
FlyWithRocket() : m_Energy(3) {}
void fly()
{
if(m_Energy > 0)
{
fly_with_rocket();
--m_Energy;
}
else
{
fly_out_of_energy();
}
}
private:
void fly_with_rocket()
{
std::cout << __FUNCTION__ << std::endl;
}
void fly_out_of_energy()
{
std::cout << __FUNCTION__ << std::endl;
}
unsigned int m_Energy;
};
新的鸭类型:
class RubberDuck
: public Duck
{
public:
RubberDuck()
: Duck(&MuteQuack::quack, std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket)))
, m_flyrocket()
{
}
private:
FlyWithRocket m_flyrocket;
};
从现在开始,我想知道成员初始化顺序的规则。基本
Duck
在成员m_flyrocket
之前初始化,但是请注意,基本Duck
是使用尚未初始化的绑定(bind)m_flyrocket
初始化的。结果是,当我在VS2013中运行该程序时,该程序在运行时不会出现任何问题。
但是代码实际上不安全吗?如果没有,如何修改为更好的设计?
最佳答案
这是不安全的,但是除非您从基类构造函数中调用m_Fly()
,否则不太可能破坏它。
不过,您可以通过以下两种方法轻松避免这种情况:
std::function
,然后将m_Fly
重新分配给派生类构造函数中的绑定(bind)仿函数RubberDuck()
: Duck(&MuteQuack::quack, std::function<void()>())
{
m_Fly = std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket));
}
FlyWithRocket
本身用作仿函数(只需将void fly
重命名为void operator()
),然后按值传递它而不是保留私有(private)成员(它将由m_Fly
函数对象拥有,并且您可以根据需要通过std::function::target<FlyWithRocket>()
访问它)class FlyWithRocket {
public:
FlyWithRocket() : m_Energy(3) {}
void operator() () {
// ...
RubberDuck()
: Duck(&MuteQuack::quack, FlyWithRocket()) {}
关于c++ - 具有状态的C + 11战略模式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/23360892/