在 C++11 中的析构函数之后覆盖标识符

Posted

技术标签:

【中文标题】在 C++11 中的析构函数之后覆盖标识符【英文标题】:Override identifier after destructor in C++11 【发布时间】:2013-07-29 04:53:15 【问题描述】:

虚析构声明后的覆盖标识符有什么特殊含义吗?

class Base

public:
    virtual ~Base()
    

    virtual int Method() const
    
;

class Derived : public Base

public:
    virtual ~Derived() override
    

    virtual int Method() override // error: marked override, but does not override - missing const
    
;

在虚拟方法上使用覆盖标识符作为检查很有用:当 Base 虚拟方法实际上没有被覆盖时,编译器将报告错误。

虚拟析构函数的覆盖是否也有任何意义/功能?

【问题讨论】:

编译器告诉你什么? 关于 ~Derived() 覆盖它什么也没说,它编译没有任何问题。我的意思是它是否有任何特殊含义。 Method() 覆盖当然是错误的,因为它缺少 const。 (我把它作为例子) 如果基地不是虚拟的,它does NOT compile。 【参考方案1】:

不是override有特殊含义,而是析构函数本身:

10.3 虚函数

6/尽管析构函数不是继承的,但在派生的析构函数 类覆盖声明为虚拟的基类析构函数;见 12.4 和 12.5.

如果你把它和前面的条款结合起来:

5/如果一个虚函数被标记了 virt-specifier override 并且 不覆盖基类的成员函数,程序是 格式不正确。 [示例:

struct B  
    virtual void f(int); 
; 

struct D : B
 
    void f(long) override; // error: wrong signature overriding B::f
    void f(int) override; // OK 
; 

——结束示例]

您可以看到,如果一个析构函数被标记为override,但基类没有virtual 析构函数,则程序是非良构的。

【讨论】:

不幸的是,VS2010 给出了“错误 C3665:'MyClass::~MyClass':在析构函数上不允许覆盖说明符'覆盖'”。也许在更现代的编译器中这种行为得到了改进...... 假设析构函数在基类中是虚拟的,是否建议在派生类中使用覆盖标记析构函数? Sutter 和 Meyers 提供了明确的指导方针,表明您应该在重写虚函数时使用 override,但他们没有专门讨论析构函数。我看不出它会有什么伤害,但程序员真的会这样做吗? 仅供参考:@TimMB 的评论 - VS 2017 确实允许在派生类中覆盖虚拟 dtor。【参考方案2】:

是的。如果基本析构函数不是虚拟的,那么override 标记将导致程序无法编译:

class Base

public:
    ~Base()
    
;

class Derived : public Base

public:
    virtual ~Derived() override //error: '~Derived' marked 'override' but does
                                //        not override any member functions
    
;

【讨论】:

有什么理由同时使用virtualoverride 吗?析构函数有特殊情况吗?我认为约定的智慧是同时使用两者,因为override 使virtual 对于普通方法来说是多余的,但我不确定析构函数。 个人意见是,这取决于给定组织和个人的编码约定。出于习惯,我现在都使用两者。如果我出于习惯覆盖了虚拟功能,我会添加虚拟限定符。即使在引入 override 关键字之后,这种习惯仍然存在。 @MarkLakata,它们仍然有不同的含义。如果你愿意,你可以覆盖一个父方法,而你自己的方法对你的后代来说是虚拟的。 @yano,这不是真的,如果某些东西在基类中声明为虚拟,那么它在每个派生类中都是隐式虚拟的。但是,您可以使用派生类中的虚拟方法来隐藏(而不是覆盖)非虚拟基类方法。 @yano 所说的是 final 关键字,它确保方法不能在派生类中被覆盖,而它最初是一个虚拟方法。

以上是关于在 C++11 中的析构函数之后覆盖标识符的主要内容,如果未能解决你的问题,请参考以下文章

gcov 报告的析构函数中的分支是啥?

csharp C#.cs中的析构函数

可连接 std::thread 的析构函数

在 C# 中,类中的析构函数和 Finalize 方法有啥区别?

C++中的析构函数

cpp中的析构函数会自动调用吗?即使析构函数没有提及非动态变量,它们是不是也会被删除?