【发布时间】:2014-04-29 09:35:20
【问题描述】:
本书Head First Design Patterns 中的Strategy Pattern 示例是在[here] 用C++ 编写的。我正在练习根据Effective GoF Patterns with C++11 and Boost 将其转换为 C++11 样式,如下所示。
嘎嘎行为:
struct Quack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct MuteQuack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
飞行行为:
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 扩展到Duck 层次结构,RubberDuck 使用具有对象状态的新飞行行为FlyWithRocket。如下:
一种新的飞行行为:
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 使用绑定m_flyrocket 进行初始化,而绑定m_flyrocket 尚未初始化。
结果,当我在 VS2013 中运行它时,它在运行时没有任何问题。
但是代码真的不安全吗?如果没有,我该如何修改为更好的设计?
【问题讨论】:
-
主要问题是“是否将未初始化的对象传递给构造函数未定义的行为?”。我猜在大多数情况下,只要您在构建过程中不访问它,它就应该起作用,但是这个答案表明它是未定义的行为,因此不安全:stackoverflow.com/a/22203006/104774
标签: c++ design-patterns c++11