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

Fra*_*ank -1 c++ qt pointers object-lifetime qml

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

void Foo::func()
{
    ...
    Bar b;
    b.func2();
}
Run Code Online (Sandbox Code Playgroud)

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

一些背景信息:

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

Chr*_*phe 6

严重的设计问题?

this指针不能被阻止.与所有原始指针一样,在解除引用之前必须确保它是有效的.

但这不是全部:如果Foo调用的fun2()是自动存储持续时间的本地对象怎么办?

  • 如果你通过调用它的析构函数来破坏函数调用中的对象,你必须确保在同一个地方仍然有一个有效的对象:否则在离开定义了对象的块时自动调用析构函数可能导致未定义的行为.
  • 如果您delete是对象而不是仅仅销毁它,那么在任何情况下它都将是未定义的行为.

智能指针的替代设计

解决这种情况的一种方法是使用工厂创建所有FooBar对象(确保构造函数不公开),并让这些工厂返回. shared_ptr

这样做的好处是,如果不再使用某个对象,它将会破坏自身.这比手动管理破坏更加清洁.

然而,你面临几个挑战:

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

与州的替代设计

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

这可以实现:

  • 要么非常好地与州设计模式(但这可能需要一些广泛的重构),
  • 或者用简单的旗帜.然后在每个成员函数的开头检查它,并在访问可能会改变对象状态的调用之后的数据成员之前进行检查.这仍然容易出错并需要分析,但需要进行大部分"本地"更改,从而为重构提供更大的灵活性.

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

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