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

GMock测试接口与Rule of 5的合规性及代码冗余疑问

C++接口类遵循Rule of 3/5的疑问及解答

问题描述

我定义了一个用于GMock测试的接口类:

class Turtle {
  ...
  virtual ~Turtle() {}
  ...
}

代码检查工具提示需遵循Rule of 3,于是我添加了:

Turtle() = default;
  Turtle(const Turtle& x) = default;
  Turtle& operator=(const Turtle& x) = default;

之后工具仍提示需添加移动构造函数和移动赋值运算符,我又补充了:

Turtle(Turtle&& x) = default;
  Turtle& operator=(Turtle&& x) = default;

这符合Rule of 5的要求,但每个继承该接口的类都需要重复添加虚析构及这5个默认特殊成员函数。我有两个疑问:

  1. 我的实现方式是否正确?
  2. 是否必须编写如此多的样板代码?

解答

1. 实现方式的正确性

你的实现是语法正确的,但从设计角度看,对于纯接口类(仅包含虚函数/纯虚函数、无非静态成员变量的类),这些显式声明的默认特殊成员函数其实没有实际执行逻辑——因为接口类本身无法实例化,所有拷贝、移动操作都是针对派生类的。

需要重点注意:虚析构的声明是必须的,这是为了保证通过基类指针/引用销毁派生类对象时,能正确调用派生类的析构函数,避免内存泄漏。而其他特殊成员函数的默认声明,更多是满足代码检查工具的规则要求,本身不会引入错误。

2. 避免样板代码的方案

不需要重复编写这些代码,有两种常用方案:

方案1:封装通用接口基类

创建一个通用的接口基类,把虚析构和所有默认特殊成员函数都封装进去,让所有业务接口类继承它:

// 通用接口基类,封装重复的样板代码
class BaseInterface {
protected:
    // 保护构造函数,禁止直接实例化基类
    BaseInterface() = default;
    virtual ~BaseInterface() = default;

    // 默认拷贝/移动操作
    BaseInterface(const BaseInterface&) = default;
    BaseInterface& operator=(const BaseInterface&) = default;
    BaseInterface(BaseInterface&&) = default;
    BaseInterface& operator=(BaseInterface&&) = default;
};

// 业务接口类只需专注于声明接口方法
class Turtle : public BaseInterface {
public:
    virtual void forward(int distance) = 0;
    virtual void turn(int degrees) = 0;
    // ...其他接口方法
};

这样所有派生的接口类都不需要重复编写那些样板代码,只需要定义自身的接口方法即可。

方案2:调整代码检查规则(若允许)

如果你的代码检查工具支持自定义规则,可以针对纯接口类放宽Rule of 3/5的要求——因为纯接口类无法实例化,其特殊成员函数的声明更多是形式上的,不会影响实际运行逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 20:51:19