【问题标题】:Is the C++ core guideline C35 "A base class destructor should be either public and virtual, or protected and nonvirtual" wrong for interface classes?对于接口类,C++ 核心准则 C35“基类析构函数应该是公共的和虚拟的,或者受保护的和非虚拟的”是否错误?
【发布时间】:2020-06-07 06:21:44
【问题描述】:

假设我有以下接口类以“写入接口,而不是实现”:

class IDrawable
{
public:

    virtual void
    Draw() const = 0;

protected:

    ~IDrawable() = default;
};

客户端不应通过接口指针删除动态分配的可绘制对象,因此IDrawable 的析构函数被设为受保护且非虚拟,根据C++ Core guideline C.35: A base class destructor should be either public and virtual, or protected and nonvirtual.

现在实现这个接口的类:

class CDrawable : public IDrawable
{
public:

    void
    Draw() const override;
};

当然,这会发出警告:

CDrawable 具有虚函数但非虚析构函数。

为了解决这个问题,我们现在必须向CDrawable 添加一个虚拟析构函数。但是在派生类中使用虚拟析构函数感觉就像是代码异味,我之前没见过(?)在IDrawable 中使用虚拟受保护析构函数不是更有意义吗,与指南相反说?

【问题讨论】:

  • 这里的问题不在于 C.35 本身。就是编译器和 IsoCppCoreGuidelines 有不同的看法。如果你愿意,你可以尝试 CDrawable final 并检查编译器是否仍然发出警告。

标签: c++ inheritance interface virtual-functions cpp-core-guidelines


【解决方案1】:

技术上没有问题。您的 CDrawable 有一个公共的非虚拟析构函数(隐式定义)。调用它不会导致未定义的行为,当然除非它是在派生自CDrawable 的类上调用的。如果您只有对 IDrawable 的引用并调用了它的析构函数,您将跳过派生类的销毁(我认为会导致 UB),但由于它不是公开可访问的,所以这不是问题。

是的,您会收到警告。然而,这个警告就是这样,表明某事可能有问题。在这种情况下,它不是。

【讨论】:

  • 大多数来自编译器的警告都可以被抑制(或默认被抑制)。在这种情况下,可能有理由禁止此特定警告。
猜你喜欢
  • 2013-11-03
  • 2012-11-06
  • 2021-08-22
  • 2023-03-23
  • 2017-06-02
  • 2020-03-06
  • 2012-06-26
  • 1970-01-01
  • 2016-01-22
相关资源
最近更新 更多