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

如何在C++中通过继承删除构造函数与运算符?

实现不可拷贝/不可移动类的优雅方案

需求背景

需要实现两个辅助类no_copy和no_move,让子类继承后自动具备对应特性:

  • 继承no_copy的类,等价于手动删除拷贝构造函数和拷贝赋值运算符
  • 继承no_move的类,等价于手动删除移动构造函数和移动赋值运算符

示例效果如下:

class base : no_copy {
    /* 等价于:
    base(const base&)=delete;
    base& operator=(const base&)=delete;
    */
};

class base2 : no_move {
    /* 等价于:
    base2(base2&&)=delete;
    base2& operator=(base2&&)=delete;
    */
};

当前宏实现的问题

目前通过宏实现该功能,虽然能正常工作,但存在明显缺陷:

// 无限定名的类
#define __NO_COPY__(__class__) __class__::__class__(const __class__&)=delete; __class__& __class__::operator=(const __class__&)=delete;

// 有限定名的类
#define __NO_COPY_LIB__(__qualified_name__,__class__) __qualified_name__::__class__(const __class__&)=delete; __class__& __qualified_name__::operator=(const __class__&)=delete;

补充使用示例:

namespace wrapper
{
   class my_class {};

   __NO_COPY__(my_class);
}
__NO_COPY_LIB__(::wrapper::my_class,my_class);

宏的问题在于:

  • 语法不美观,破坏代码结构
  • 可出现在类定义或实现的任意位置,后续代码重构难度大

期望能在类定义内部直接声明,比如通过模板继承的形式:

class base : public attributes<no_copy,no_move> {};

// 对应的模板包装器
template <typename... _BCs/*Base Classes*/>
struct attributes : public _BCs... {};

核心需求是便捷定义类的拷贝/移动特性,同时支持易重构的实现方式,疑问是「通过继承基类来删除子类的构造函数/运算符是否可行」。


可行解决方案

方案1:继承式基类实现(推荐)

利用C++的规则:如果基类的拷贝/移动构造/赋值运算符被delete,子类若未显式定义对应成员,编译器会隐式删除子类的对应成员(因为生成默认版本时需要调用基类的delete成员,导致编译错误)。

实现no_copy和no_move基类:

// 不可拷贝基类
class no_copy {
protected:
    // 允许子类构造和析构,禁止外部直接实例化
    no_copy() = default;
    ~no_copy() = default;

    // 删除拷贝相关成员
    no_copy(const no_copy&) = delete;
    no_copy& operator=(const no_copy&) = delete;
};

// 不可移动基类
class no_move {
protected:
    no_move() = default;
    ~no_move() = default;

    // 删除移动相关成员
    no_move(no_move&&) = delete;
    no_move& operator=(no_move&&) = delete;
};

子类使用时直接继承,或通过模板包装器整合:

// 模板包装器,支持同时继承多个特性类
template <typename... Bases>
struct attributes : public Bases... {};

// 用法示例:同时不可拷贝+不可移动
class base : public attributes<no_copy, no_move> {};

// 单独不可拷贝
class copy_prohibited : public no_copy {};

这种方式完全符合需求,代码结构清晰,所有特性声明都集中在类的继承列表中,便于重构。

方案2:类内宏声明(非继承方式)

如果不想用继承,可以将宏限定在类内部使用,固定声明位置,提升可维护性:

#define NO_COPY(class_name) \
    class_name(const class_name&) = delete; \
    class_name& operator=(const class_name&) = delete;

#define NO_MOVE(class_name) \
    class_name(class_name&&) = delete; \
    class_name& operator=(class_name&&) = delete;

使用示例:

class base {
public:
    base() = default;
    ~base() = default;

    NO_COPY(base)
    NO_MOVE(base)
};

方案3:C++20标准库方案

C++20开始,标准库在<utility>头文件中提供了std::noncopyable,直接继承即可实现不可拷贝:

#include <utility>

class base : public std::noncopyable {};

对于不可移动特性,可自行实现no_move基类,与std::noncopyable组合使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:04:58