蔚淦丞
发布于 2026-09-03 / 18 阅读
0
0

C++构造、析构函数访问权限 特殊场景

默认 public 构造 / 析构是常规用法,本文不记录。 只记录工程特殊用法 + 精准限制 + 真实作用

基础核心规则(5 条)

  1. 构造权限:控制能不能 new / 栈实例化

  2. 析构权限:控制能不能 delete / 栈自动析构

  3. protected:子类可见,外部不可见

  4. 构造、析构 和拷贝无关,禁止拷贝必须单独 =delete

  5. 多态调用、多态销毁是两件完全独立的事

    • 多态调用:由普通 virtual 函数决定

    • 多态销毁:由析构是否 public + virtual 决定


1. 构造 protected、析构 protected

真实限制

  1. 外部不能实例化基类(栈、堆都不行)

  2. 子类可以正常继承、正常构造析构

  3. 不建议多态调用(基类写 virtual 函数完全没问题,但不建议这么做)

  4. 禁止多态销毁:不能 基类指针 delete 子类对象(因此,如果希望多态调用,不应该protected析构函数)

为什么析构也要 protected?——不需要多态调用

  • 如果析构写 public: 使用者可以 基类指针 new 子类,然后 delete → 无虚析构 + 父类指针删除 = 未定义行为、内存泄漏

  • 这种父类通常不会多态调用

用途

纯工具基类,只用来被继承、也不会多态调用。

补充:常见于NonCopyable类

这个类还需要delete拷贝构造、拷贝赋值,双 protected 管不了拷贝,想要子类不可拷贝,必须手动 delete 拷贝构造 / 赋值。


2. 构造 protected、析构 public virtual(标准抽象接口基类)

限制

  1. 外部不能实例化基类

  2. 子类完全正常使用

  3. 支持完整多态:多态调用 + 多态销毁全部合法

设计优势

  1. 不需要写纯虚函数也能禁止实例化

  2. 不需要写外部析构实现(对比纯虚析构)

  3. 语义清晰:专供继承、支持多态

用途

接口基类、统一抽象层、需要用父类指针管理子类对象。


3. 构造 private

限制

  1. 外部完全无法创建对象

  2. 无法被继承(子类构造访问不到父类构造)

用途

单例类、完全禁止外部实例化。


4. 析构 private(构造 public)

限制

  1. 不能栈对象

  2. 可以 new,不可以外部 delete

  3. 无法被继承

用途

类内部自主管控资源释放,禁止外部销毁。


5. 构造 private、析构 private

限制

  1. 外部无法创建任何对象

  2. 不可继承

  3. 仅静态对象可用

现实可用场景非常少

场景 1:只放静态成员的工具类(C++ 老式写法)

class MathUtil
{
private:
    MathUtil() = default;
    ~MathUtil() = default;
public:
    static int add(int a,int b){return a+b;}
};

目的:禁止任何人实例化这个类,这个类只用来打包一堆静态函数。

现代 C++ 更推荐直接用 namespace,而不是一个不能实例化的类。所以这种写法属于过时、少见。

场景 2:配合友元,做严格受控创建(极少)

只有指定的友元类才有权限创建、销毁该对象,相当于一种对象创建权限隔离。业务代码几乎不会用到。


最终极简核心总结(背诵版)

  1. 双 protected(NonCopyable) 可多态调用、不可多态销毁、不可实例化基类、可继承、需手动 delete 拷贝。

  2. 构造 protected + 虚析构 public 完全支持多态(调用 + 销毁)、不可实例化、标准接口基类。

  3. 构造 private 禁止实例化、禁止继承 → 单例。

  4. 析构 private 禁止外部销毁、强制内部管理生命周期。


评论