You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C++17中禁用类的非动态构造函数(不删除析构函数)

实现仅允许动态构造的C类(C17)

当然可以实现这个需求!在C++17标准下,我们可以通过控制析构函数的访问权限+友元机制,完美达成“仅能通过new构造、禁止栈上创建且不删除析构函数”的目标。

核心思路

栈上创建的对象会在离开作用域时自动调用析构函数,如果我们把析构函数设为私有,编译器会因为无法生成自动析构的代码而直接报错。但这样会带来一个问题:delete动态对象时也需要调用析构函数,同样会被权限阻止。解决办法很简单——把全局的operator delete声明为类的友元,让它有权访问私有析构函数,这样delete就能正常工作了。

示例代码

#include <cstdlib> // 确保全局operator delete的声明可见

class Foo {
public:
    Foo() {} // 构造函数设为public,允许new表达式调用

private:
    ~Foo() {} // 析构函数设为private,阻止栈对象的自动析构

    // 将全局operator delete设为友元,使其能调用私有析构函数
    friend void operator delete(void* ptr) noexcept;

    // 如果需要支持数组形式的new/delete,添加以下友元声明:
    // friend void operator delete[](void* ptr) noexcept;
};

int main() {
    Foo A; // ❌ 编译错误:无法访问Foo的私有析构函数(编译器需要自动调用它)
    Foo* B = new Foo(); // ✅ 正常编译:构造函数是public的
    delete B; // ✅ 正常运行:operator delete是友元,可调用私有析构函数
}

补充说明

  • 这个方案完全遵循C++17标准,不需要依赖任何编译器扩展。
  • 如果你的业务场景用到了placement new,可能需要额外声明对应的operator delete重载为友元,但对于普通的new/delete场景,上面的代码已经足够。
  • 若涉及类继承,需要调整基类与派生类的析构函数访问权限,但单类场景下这个方案可以直接使用。

内容的提问来源于stack exchange,提问作者user3366592

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:25:45