Ví dụ về Strategy Pattern từ sách, Head First Design Patterns, được viết bằng C++ tại [here]. Tôi đang thực hành để chuyển đổi nó thành phong cách C++ 11 theo Effective GoF Patterns with C++11 and Boost như hiển thị dưới đây.Mẫu chiến lược C + 11 có trạng thái
Các Quack hành vi:
struct Quack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct MuteQuack {
static void quack()
{
std::cout << __FUNCTION__ << std::endl;
}
};
Các Fly hành vi:
struct FlyWithWings {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
struct FlyNoWay {
public:
static void fly()
{
std::cout << __FUNCTION__ << std::endl;
}
};
Các Duck hệ thống cấp bậc:
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)
{
}
};
Cho đến nay rất tốt, khách hàng hoạt động tốt.
int main()
{
MallardDuck x1;
x1.perform_quack();
x1.perform_fly();
PaintedDuck x2;
x2.perform_quack();
x2.perform_fly();
return 0;
}
Bây giờ tôi muốn mở rộng đến một lớp học mới RubberDuck
để Duck hệ thống cấp bậc, và RubberDuck
sử dụng một hành vi bay mới FlyWithRocket
trong đó có một trạng thái đối tượng. Như sau:
Một mới Fly hành vi:
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;
};
Một mới Duck loại:
class RubberDuck
: public Duck
{
public:
RubberDuck()
: Duck(&MuteQuack::quack, std::bind(&FlyWithRocket::fly, std::ref(m_flyrocket)))
, m_flyrocket()
{
}
private:
FlyWithRocket m_flyrocket;
};
Từ bây giờ tôi đang tự hỏi rằng các quy tắc của trật tự khởi tạo thành viên . Các cơ sở Duck
khởi tạo trước khi các thành viên m_flyrocket
, nhưng lưu ý rằng các cơ sở Duck
được khởi tạo với ràng buộc m_flyrocket
mà chưa được khởi tạo. Kết quả là tôi chạy nó trong VS2013, điều này làm việc mà không có một cái gì đó sai tại thời gian chạy.
Nhưng mã có thực sự không an toàn không? Nếu không, làm thế nào tôi có thể sửa đổi một thiết kế tốt hơn?
Câu hỏi lớn là "đang đi qua một đối tượng không khởi tạo một hành vi undefined constructor? ".Tôi đoán rằng trong hầu hết các trường hợp, điều này sẽ hoạt động miễn là bạn không truy cập nó trong khi xây dựng, nhưng câu trả lời này cho thấy rằng đó là hành vi không xác định, vì vậy không an toàn: http://stackoverflow.com/a/22203006/104774 – stefaanv