如何防止用户破坏对象

Posted

技术标签:

【中文标题】如何防止用户破坏对象【英文标题】:How to prevent user from destroying an object 【发布时间】:2011-05-20 19:27:20 【问题描述】:

我想从一个函数返回一个类的实现。该函数位于库中。我想防止用户破坏我返回的对象。我怎样才能做到这一点?

编辑:示例。

与世界的接口:

class Base

   public:
      virtual void foo() = 0;
;

Base* GetFoo();

实施 - 内部:

class Bar : public Base

    public:
        void foo()  //Do something
;

Base* GetFoo()

   return new Bar

【问题讨论】:

有点超出原始问题的范围,但我不确定你为什么要使用单独的函数来获取接口基础(bar 的实例)。为什么不使用工厂方法。 如果用户尝试,只需对计算机进行编程以炸毁显示器。 我相信你希望 Bar() 的构造函数也是私有的? 不要返回指针(指针暗示他有删除的选项(虽然不是真的))。如果您返回引用,则用户没有理由删除它。 【参考方案1】:

您为什么要这样做?无论如何,用户都应该获得返回对象的副本,并且应该由他们决定是否分配或取消分配副本。

【讨论】:

-1:一个特别无益的答案——在复杂系统中,这个问题提出了一个现实的且并不罕见的要求。如果他们被授予某个集中式服务的访问器,那么“获取副本”可能完全没用,并且该服务很可能会打开一些不应受到构造函数和析构函数持续影响的硬件或操作系统资源。即使是智能指针也意味着一些性能和内存使用的妥协。解释一种方法的优缺点是合理的,但忽略这个问题并不好。 -1。同意托尼。特别是如果您正在做对性能敏感的事情,您不希望用户通过破坏来弄乱对象池(从而不使池回收该内存)。甚至用户也应该避免建造,因为它很昂贵。【参考方案2】:

您可以使用私有析构函数并创建一些方法 (release()) 以允许以受控方式释放对象。

Private destructors What is the use of having destructor as private?

【讨论】:

【参考方案3】:

你不能禁止你图书馆的使用者在清理一把上膛的枪时射中自己的腿。 IE。即使您返回一个常量引用,也可以从中获取地址,然后 delete 它。所以即使在这种情况下,你也应该让你的代码保持稳定。

附:私有析构函数 (@nc3b) 对类的进一步使用施加了限制(例如,不再有本地非动态实例),因此请明智地考虑它们。

【讨论】:

我不同意应该让他们的代码在所有情况下保持稳定,包括当用户明显试图破坏你的库时,你刚才描述的听起来像.在可行的情况下可以这样做,但在许多情况下,试图解释人们可能提出的各种愚蠢行为是愚蠢的。 @Matti,我同意,不是每一个案例都应该得到照顾,但我相信在每一种情况下,白痴保护和自我健康检查之间都有一个合理的折衷,所以说。【参考方案4】:

如果您的 returning 是 new 对象,那么您没有理由需要阻止用户 delete 对其进行操作。

但是,您不应该留下任何关于删除责任的问题。相反,要么使用智能指针返回值,要么使用多态 pImpl 模式(其中非多态包装器包含指向多态实现的智能指针 - 通常是提供值语义的智能指针,例如 this )只是返回一个派生实例。

【讨论】:

【参考方案5】:

并且在您从基础派生时回答您的问题,因此您不能将基础析构函数设为私有。您可以通过受保护的析构函数来实现您的目标。

【讨论】:

【参考方案6】:

返回 shared_ptr<Base> 并自己保留指针的副本。无论用户如何处理他的shared_ptr<Base>,该指针都会使对象保持活动状态。您甚至可以考虑返回 weak_ptr<Base>,以强调对象的生命周期仅取决于您的心血来潮。

【讨论】:

以上是关于如何防止用户破坏对象的主要内容,如果未能解决你的问题,请参考以下文章

持有C ++引用是否可以防止变量被破坏?

如何防止反序列化破坏单例

如何防止反序列化破坏单例

如何防止反序列化破坏单例

如何防止反序列化破坏单例

如何防止卡巴斯基破坏我下载的文件?