删除“this”指针后阻止对象使用

时间:2018-05-08 08:44:47

标签: c++ qt pointers qml object-lifetime

我正在处理具有以下问题的应用程序。基本上有很多对象可能会破坏自己。

void Foo::func()
{
    ...
    Bar b;
    b.func2();
}

此处func2可能会破坏调用它的foo对象。由于不太可能发生这种情况,我想确保在此调用之后不能访问foo对象的任何成员变量,因为我不能保证它们仍然有效。如果对b的这个调用是最后一次调用我完全没问题,但由于我不是唯一一个在这个项目上工作并且销毁不明显的人,我想在这些调用之后实现阻止使用this的东西。有没有办法在不完全重构当前设计的情况下实现这一点(因为它在整个项目中广泛使用)?

一些背景信息:

这是一个Qt UI应用程序,它使用QML来跟踪一堆“屏幕”(屏幕是QML +相应的C ++模型)。我的示例中的Bar类是“堆栈管理器”,它控制着屏幕的生命周期。这是一个单身人士(我知道)。 Foo类是特定QML的C ++模型。函数Foo::func()是可以从QML中的用户输入或其他系统事件调用的函数。该函数通常处理事件,但偶尔它可以告诉屏幕管理器删除一个或多个屏幕,这些屏幕又删除对应于该屏幕的模型(可能是调用模型)。

1 个答案:

答案 0 :(得分:6)

严重的设计问题?

无法阻止this指针。与所有原始指针一样,您必须确保它在解除引用之前有效。

但并非全部:如果调用Foo的{​​{1}}是自动存储持续时间的本地对象,该怎么办?

  • 如果您通过调用析构函数来销毁函数调用中的对象,则必须确保在同一位置仍然存在有效对象:否则自动调用离开定义对象的块时的析构函数可能导致未定义的行为。
  • 如果您fun2()该对象而不仅仅是销毁它,那么它将是未定义的behavior in any case

智能指针的替代设计

摆脱这种情况的一种方法是使用factories创建所有deleteFoo对象(确保构造函数不公开),并让这些工厂返回{ {1}}。

这样做的好处是,如果不再使用某个对象,它将自行销毁。这比手动管理破坏更加清晰。

你面临着一些挑战:

  • 您必须重构所有代码以通过智能指针替换原始指针
  • 为了避免由于交叉引用导致的无限生活(两个对象保持每个指向另一个的slart指针),你需要弄清楚何时使用Bar(如果指针必须确保对象仍然存在)以及何时使用shared_ptr(即指针不能保持对象存活)。

带状态的替代设计

另一种选择是使用状态来区分可以使用的活动对象和不再使用的已故对象。因此,您不必删除对象,而是调用状态更改函数来清理/重置对象。

这可以实施:

  • 非常好用state design pattern(但这可能需要一些广泛的重构),
  • 或带有简单的旗帜。然后在每个成员函数的开头检查它,并且在访问可能改变对象状态的调用之后的数据成员之前。这仍然容易出错,需要分析,但主要需要" local"改变并为重构提供更多灵活性。

这种方法的优点是状态更改函数非常简单(当前在析构函数中的大部分内容,但避免它们可能是第二次意外完成)并使棘手的部分非常明显。

困难在于确保已故物品的清洁效果良好。因此,您需要解决前面已提到的所有权问题,并确保在操作过程中不删除这些对象。