Добрый день. Теоретический вопрос про паттерн Состояние.
Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?
class Context;
class State
{
public:
virtaul ~State() {}
virtual void f() = 0;
protected:
Context* c_;
};
class A: public State
{
public:
A(Context* c): c_(c) {}
void f()
{
//Тут нужно создать состояние B и изменить c_->s_, вызвать B::f() и удалить состояние A
c_->s_ = new B(c_);
c_->s_->f();
delete this; //неприятно выглядит
}
};
class Context
{
public:
Context(): s_(new A(this)) {}
void f() { s_->f(); }
private:
State* s_;
};
Как можно это лучше реализовать?
А если так?
class State {
public:
virtual ~State() {}
virtual State * change() = 0;
};
class StateA: public State {
State * change();
};
class StateB: public State {
State * change() {
return new StateA();
}
};
State * StateA::change() {
return new StateB();
}
class Context {
public:
Context():
m_state(new StateA())
{}
void switch_state() {
m_state.reset( m_state->change() );
}
private:
std::auto_ptr<State> m_state;
}
Здравствуйте, BitField, Вы писали:
Понял идею, спасибо. Действительно, в первую очередь надо взять auto_ptr
Но предполагается, что A сам решит в какое состояние перейти контексту и переведет контекст в это состояние (то есть в B, C, D и т.д.).
Забыл отметить, что в состояния имеют friend доступ к данным контекста
class Context
{
//...
friend class State;
};
Здравствуйте, Wody, Вы писали:
W>Добрый день. Теоретический вопрос про паттерн Состояние.
W>Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?
W>Как можно это лучше реализовать?
Если состояния это
код без данных, то можно использовать placement new т.е вместо delete this написать
(new (this) B)->f();
Выделенное важно.
Здравствуйте, Kernan, Вы писали:
K>Здравствуйте, Wody, Вы писали:
W>>Добрый день. Теоретический вопрос про паттерн Состояние.
W>>Имеем контекст, абстрактный класс состояния и два конкретных состояния (A, B). Как правильно в объекте A сменить состояние контекста и запустить метод f конкретного состояния B?
W>>Как можно это лучше реализовать?
K>Если состояния это код без данных,
а также без виртуальных функций, или при наследовании состояния не использовалось виртуальное наследовании, или не было множественного наследования состояния и компилятор без empty base optimization...
тогда да...
K> то можно использовать placement new т.е вместо delete this написать
K>K>(new (this) B)->f();
K>
K>Выделенное важно.