我有一个这种类型的成员指针:
const TopState<TestHSM>* state_;
state_
属于多态类型。
TopState
是基础:
template<typename H>
struct TopState {
//... functions etc
};
有一些层次结构,最后LeafState
不是抽象的:
template<typename H, unsigned id,
typename B=CompState<H,0,TopState<H> > >
struct LeafState : B {
//...functions
static const LeafState obj;
};
以下对象代表状态:
//indentation to indicate state nesting
typedef CompState<TestHSM,0> Top;
typedef CompState<TestHSM,1,Top> S0;
typedef CompState<TestHSM,2,S0> S1;
typedef LeafState<TestHSM,3,S1> S11;
typedef CompState<TestHSM,4,S0> S2;
typedef CompState<TestHSM,5,S2> S21;
typedef LeafState<TestHSM,6,S21> S211;
仅注意S11
和S211
(LeafState
)可以实例化。
我有一个TestHSM
类,看起来像这样:
class TestHSM {
public:
TestHSM() {
state_ = new S11;
}
//fix destruction - problem
~TestHSM() {
//reset to s11
// state_ = &S11;
// delete state_;
// state_ = 0;
}
void next(const TopState<TestHSM>& state)
{
state_ = &state;
}
private:
const TopState<TestHSM>* state_;
};
我现在的问题是创建state_
对象。见上面的构造函数。这有效,但我不完全确定这是否是正确的做法?
S11
是第一个可以实例化对象的状态 - 在我的程序中S11
是启动时的第一个状态。代码'按预期工作'。或者似乎无论如何。但我不确定这是实现拳头状态的最佳方法还是正确方法?
此外,如果我这样做,那么当我尝试删除state_
时,我会收到堆内存运行时错误 - 请参阅注释掉的析构函数代码。
有什么建议吗?
安格斯
答案 0 :(得分:0)
您的对象构造和用法是正确的和标准的C ++。唯一的问题是您注意到的破坏代码。您正在尝试使用类型的指针 - 这不会起作用,编译器不会让您这样做。析构函数应该像释放内存一样简单:
~TestHSM() {
if (state_) {
delete state_;
state_ = 0;
}
}
此外,请确保在更改状态时删除以前的状态。即next()函数应如下所示:
void next(TopState<TestHSM> *state)
{
if (state_)
delete state_;
state_ = state;
}
您应该始终将使用new
构建的状态传递给下一个函数,并在不需要时让TestHSM
释放它:
int main() {
TestHSM test;
test.next(new S211());
// No freeing, TestHSM destructor frees everything
}
答案 1 :(得分:0)
所提出的课程TestHSM
未遵循the rule of three。它缺少复制构造函数和复制赋值运算符,或者是一种禁止它们的方法。
您最好的选择是让其他人为您处理资源管理。例如,使用std::unique_ptr
或boost::scoped_ptr
成员。这些选项中的任何一个都将禁止TestHSM
的副本。如果需要复制的能力,则必须手动编写复制构造函数,以及状态的一些虚拟复制机制(即clone()
成员函数)。