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

C++构造函数访问控制:抽象基类禁实例化的优雅实现方案

C++抽象异常基类无冗余实现方案

你选择修改访问权限的思路方向完全正确,之前遇到的冗余问题不需要靠纯虚函数方案妥协,用受保护的虚析构函数 + 构造函数继承就可以零冗余实现禁止直接实例化基类的需求。

方案原理

C++语法规定,如果一个类的析构函数为protected访问级别,外部代码将无法直接在栈、堆上创建该类的独立实例——因为对象生命周期结束时必须调用析构函数,外部无访问权限时编译器会直接拦截实例化操作。
这个方案天然规避了另外两种方案的缺陷:

  • 不需要给基类添加无业务意义的纯虚函数,派生类无需额外实现冗余接口
  • 不需要手动枚举、重写基类的所有构造函数做转发,完全消除重复代码

实现代码

#include <stdexcept>
#include <string>

// 抽象异常基类
struct AbstractException : public std::runtime_error {
    // 一行直接继承std::runtime_error的所有构造函数,无需手动写转发逻辑
    using std::runtime_error::runtime_error;
protected:
    // 仅需将析构函数设为protected,即可禁止外部直接实例化
    ~AbstractException() override = default;
};

// 具体业务异常类
struct BizException : public AbstractException {
    // 一行继承基类所有构造函数,即可直接使用
    using AbstractException::AbstractException;
};

struct ParamException : public AbstractException {
    using AbstractException::AbstractException;
};

使用效果验证

int main() {
    // 编译报错:无法访问AbstractException的protected析构函数,禁止直接实例化基类
    // throw AbstractException("base error");

    // 派生类可正常实例化、抛出
    throw BizException("biz process failed");
    return 0;
}

方案优势

  • 零额外开销:std::runtime_error本身就带虚析构函数,我们只是修改其访问级别,不会增加任何虚表或运行时成本
  • 行为完全符合预期:可以正常通过const AbstractException&捕获所有派生异常,和普通异常继承体系的使用方式完全一致
  • 扩展成本极低:新增具体异常类只需要写两行继承+using构造的代码,不需要重复写任何构造转发逻辑
  • 规避了using构造的权限问题:基类构造函数可以直接保持public访问级别,不需要手动调整访问权限,派生类通过using继承的构造函数默认就是public,可直接调用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 04:18:23