用 C++ 设计和实现接口
Designing and implementing an interface in C++: I'm damned if I do and I'm damned if I don't
我需要一些有关 C++ 接口继承和编码方面的帮助。我正在创建一个状态机,我将从中派生出另一个状态机。因此我有两个相互作用的部分,一个 StateMachine
和一个 State
。问题是,对于这种设计,我无法从 StateMachine
或 DerivedStateMachine
.
派生出专门的 State
class StateMachine; //fwd
class State {
public:
virtual void action(StateMachine *engine) = 0;
virtual ~State() = default;
};
class StateMachine {
public:
StateMachine() = default;
explicit StateMachine(State &state) : state_(&state) {};
virtual void setState(State &state) {
state_ = &state;
}
[[nodiscard]] virtual State *getState() const {
return state_;
}
protected:
State *state_ = nullptr;
};
class DerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
return special_thing_;
}
void setSpecialState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
DerivedStateDependsOnGeneralStateMachine
的问题是 StateMachine*
无法访问 doSpecializedThings()
方法。
class DerivedStateDependsOnGeneralStateMachine : public State {
virtual void action(StateMachine *engine) {
int important_value = engine->doSpecializedThings();
};
};
DerivedStateDependsOnDerivedStateMachine
的问题是您不能用不同的参数覆盖父方法。
class DerivedStateDependsOnDerivedStateMachine : public State {
void action(DerivedStateMachine *engine) override {
engine->doSpecializedThings();
};
};
任何人都可以找到摆脱我自己的这个结的出路吗?显然我在某处搞砸了设计。在这种情况下,'normal'(找不到更好的词)是什么?
编辑
为了解决这些评论,首先 @Ted Lyngmo 我正在使用我在 this post 中找到的状态机设计。奇怪的是,相互依赖是设计中内置的,但它是故意的。 StateMachine
需要始终保持对状态的引用,并且状态负责确定下一个状态。下一个状态可能取决于存储在 StateMachine
中的变量,因此在 State
.
中引用 StateMachine
很有用
为了更具体一点,我正在编写一个扑克游戏。我的想法是有一个抽象的 StateMachine
接口,我可以从中派生出一个符合该接口的 PokerEngine
状态机。我还认为我应该有一个抽象State
,从中我可以推导出一个PokerState
。这一切都可以在没有抽象级别的情况下工作,并且最初可能更容易考虑,但对我来说练习接口编码以启用依赖注入和模拟很重要。具有讽刺意味的是,在尝试做这些事情时,我违反了 Liskov 替换原则。无论如何,PokerEngine
将需要做类似 getPotAmount
的事情,这是一种我不想 any StateMachine
.
我不完全理解你的设计,但你可以像这样做你需要的:
class StateMachine; //fwd
class State {
public:
virtual void action(StateMachine *engine) = 0;
virtual ~State() = default;
};
class StateMachine {
public:
StateMachine() = default;
explicit StateMachine(State &state) : state_(&state) {};
virtual void setState(State &state) {
state_ = &state;
}
virtual void setState(int state) {};
[[nodiscard]] virtual State *getState() const {
return state_;
}
virtual int doSpecializedThings(){
std::cout << "Do StateMachine things (or nothing)" << std::endl;
return 0;
}
protected:
State *state_ = nullptr;
};
class DerivedStateDependsOnGeneralStateMachine : public State {
public:
virtual void action(StateMachine *engine) {
int important_value = engine->doSpecializedThings();
};
};
class DerivedStateDependsOnDerivedStateMachine : public State {
public:
void action(StateMachine *engine) override {
engine->doSpecializedThings();
};
};
class DerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
std::cout << "Do DerivedStateMachine things " << std::endl;
return special_thing_;
}
void setState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
class AnotherDerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
std::cout << "Do AnotherDerivedStateMachine things and" << std::endl;
std::cout << "\tcalling base class: ";
StateMachine::doSpecializedThings();
return special_thing_;
}
void setState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
int main()
{
StateMachine sm;
DerivedStateMachine dsm;
AnotherDerivedStateMachine adsm;
DerivedStateDependsOnGeneralStateMachine dsmg;
DerivedStateDependsOnDerivedStateMachine dsmd;
sm.setState (dsmg);
StateMachine * pdsm = &dsm;
pdsm->setState (dsmd);
dsm.setState (1);
dsmg.action (&dsm);
dsmd.action (&dsm);
dsmg.action (&sm);
dsmd.action (&sm);
dsmd.action (&adsm);
return 0;
}
我不明白你为什么需要 StateMachine
中的 State
,因为你正在从 State
调用 StateMachine
。
最后,我能够通过从抽象类型转换为派生类型来访问我需要的变量和方法
我需要一些有关 C++ 接口继承和编码方面的帮助。我正在创建一个状态机,我将从中派生出另一个状态机。因此我有两个相互作用的部分,一个 StateMachine
和一个 State
。问题是,对于这种设计,我无法从 StateMachine
或 DerivedStateMachine
.
State
class StateMachine; //fwd
class State {
public:
virtual void action(StateMachine *engine) = 0;
virtual ~State() = default;
};
class StateMachine {
public:
StateMachine() = default;
explicit StateMachine(State &state) : state_(&state) {};
virtual void setState(State &state) {
state_ = &state;
}
[[nodiscard]] virtual State *getState() const {
return state_;
}
protected:
State *state_ = nullptr;
};
class DerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
return special_thing_;
}
void setSpecialState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
DerivedStateDependsOnGeneralStateMachine
的问题是 StateMachine*
无法访问 doSpecializedThings()
方法。
class DerivedStateDependsOnGeneralStateMachine : public State {
virtual void action(StateMachine *engine) {
int important_value = engine->doSpecializedThings();
};
};
DerivedStateDependsOnDerivedStateMachine
的问题是您不能用不同的参数覆盖父方法。
class DerivedStateDependsOnDerivedStateMachine : public State {
void action(DerivedStateMachine *engine) override {
engine->doSpecializedThings();
};
};
任何人都可以找到摆脱我自己的这个结的出路吗?显然我在某处搞砸了设计。在这种情况下,'normal'(找不到更好的词)是什么?
编辑
为了解决这些评论,首先 @Ted Lyngmo 我正在使用我在 this post 中找到的状态机设计。奇怪的是,相互依赖是设计中内置的,但它是故意的。 StateMachine
需要始终保持对状态的引用,并且状态负责确定下一个状态。下一个状态可能取决于存储在 StateMachine
中的变量,因此在 State
.
StateMachine
很有用
为了更具体一点,我正在编写一个扑克游戏。我的想法是有一个抽象的 StateMachine
接口,我可以从中派生出一个符合该接口的 PokerEngine
状态机。我还认为我应该有一个抽象State
,从中我可以推导出一个PokerState
。这一切都可以在没有抽象级别的情况下工作,并且最初可能更容易考虑,但对我来说练习接口编码以启用依赖注入和模拟很重要。具有讽刺意味的是,在尝试做这些事情时,我违反了 Liskov 替换原则。无论如何,PokerEngine
将需要做类似 getPotAmount
的事情,这是一种我不想 any StateMachine
.
我不完全理解你的设计,但你可以像这样做你需要的:
class StateMachine; //fwd
class State {
public:
virtual void action(StateMachine *engine) = 0;
virtual ~State() = default;
};
class StateMachine {
public:
StateMachine() = default;
explicit StateMachine(State &state) : state_(&state) {};
virtual void setState(State &state) {
state_ = &state;
}
virtual void setState(int state) {};
[[nodiscard]] virtual State *getState() const {
return state_;
}
virtual int doSpecializedThings(){
std::cout << "Do StateMachine things (or nothing)" << std::endl;
return 0;
}
protected:
State *state_ = nullptr;
};
class DerivedStateDependsOnGeneralStateMachine : public State {
public:
virtual void action(StateMachine *engine) {
int important_value = engine->doSpecializedThings();
};
};
class DerivedStateDependsOnDerivedStateMachine : public State {
public:
void action(StateMachine *engine) override {
engine->doSpecializedThings();
};
};
class DerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
std::cout << "Do DerivedStateMachine things " << std::endl;
return special_thing_;
}
void setState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
class AnotherDerivedStateMachine : public StateMachine {
public:
using StateMachine::StateMachine;
int doSpecializedThings(){
std::cout << "Do AnotherDerivedStateMachine things and" << std::endl;
std::cout << "\tcalling base class: ";
StateMachine::doSpecializedThings();
return special_thing_;
}
void setState(int specialState) {
special_thing_ = specialState;
}
private:
int special_thing_;
};
int main()
{
StateMachine sm;
DerivedStateMachine dsm;
AnotherDerivedStateMachine adsm;
DerivedStateDependsOnGeneralStateMachine dsmg;
DerivedStateDependsOnDerivedStateMachine dsmd;
sm.setState (dsmg);
StateMachine * pdsm = &dsm;
pdsm->setState (dsmd);
dsm.setState (1);
dsmg.action (&dsm);
dsmd.action (&dsm);
dsmg.action (&sm);
dsmd.action (&sm);
dsmd.action (&adsm);
return 0;
}
我不明白你为什么需要 StateMachine
中的 State
,因为你正在从 State
调用 StateMachine
。
最后,我能够通过从抽象类型转换为派生类型来访问我需要的变量和方法