gpt4 book ai didi

c++ - 使用 protected 非虚拟析构函数时抑制 delete-non-virtual-dtor 警告

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:00:01 26 4
gpt4 key购买 nike

我有一个纯抽象接口(interface)类和一个实现该接口(interface)的派生类。

struct Foo
{
virtual void doStuff() = 0;
};

struct Bar : Foo
{
void doStuff() override { }
};

我的接口(interface)类没有虚拟析构函数

因此,尝试使用基类指针破坏派生实例显然是未定义的行为

int main()
{
Foo* f = new Bar;
f->doStuff();
delete f;
}

幸运的是我的编译器足够聪明,可以捕捉到这个(使用-Werror)

main.cc:15:9: error: deleting object of abstract class type ‘Foo’ which has
non-virtual destructor will cause undefined behaviour [-Werror=delete-non-virtual-dtor]
delete f;
^

我可以通过确保不尝试使用基类指针进行删除来避免这种未定义的行为

int main()
{
Bar* b = new Bar;
b->doStuff();
delete b;
}

不幸的是,它不够聪明,无法判断这个程序的格式是否正确,并吐出类似的错误

main.cc:15:9: error: deleting object of polymorphic class type ‘Bar’ which has 
non-virtual destructor might cause undefined behaviour [-Werror=delete-non-virtual-dtor]
delete b;
^

有趣的是它说可能导致未定义的行为,而不是

protected 非虚拟析构函数:

one of Herb Sutter's Guru of the Week's他给出了以下建议:

Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.

所以让我的析构函数保护为非虚拟的。

struct Foo
{
virtual void doStuff() = 0;
protected:
~Foo() = default;
};

struct Bar : Foo
{
void doStuff() override { }
};

现在,当我不小心尝试使用基类指针进行删除时,我又遇到了一次失败

int main()
{
Foo* f = new Bar;
f->doStuff();
delete f;
}
main.cc:5:2: error: ‘Foo::~Foo()’ is protected
~Foo() = default;
^
main.cc:17:9: error: within this context
delete f;
^

太好了,这给了我想要的东西。让我们修复代码,这样我就不会使用基类指针进行删除

int main()
{
Bar* b = new Bar;
b->doStuff();
delete b;
}

不幸的是,我得到了和以前一样的错误

main.cc:17:9: error: deleting object of polymorphic class type ‘Bar’ which has 
non-virtual destructor might cause undefined behaviour [-Werror=delete-non-virtual-dtor]
delete b;
^

问题:

我怎样才能两全其美?

  • 保留 delete-non-virtual-dtor 错误,因为我忘记创建 protected 非虚拟析构函数,并尝试通过基类指针删除
  • 在我使用 protected 非虚拟析构函数并通过派生类指针删除时抑制警告

超棒的额外奖励:

  • 当我忘记使用 protected 非虚拟析构函数时抑制警告,但我通过派生类指针正确删除

最佳答案

编译器告诉您问题出在 Bar 而不是 Foo。如果您要有另一个继承自 Bar 的类,请说 Baz:

struct Baz : public Bar
{
void doStuff() override { }
};

这可能会导致未定义的行为,例如这种情况

int main()
{
Bar* bar_ptr = new Baz();
bar_ptr->do_stuff();
delete bar_ptr; // uh-oh! this is bad!
}

因为 Bar 中的析构函数不是虚函数。因此,解决方案是按照建议将 Bar 标记为最终的,或者将 Bar 中的析构函数设为虚拟(因为它是公共(public)的),或者根据 Herb 的建议使其受到保护。

关于c++ - 使用 protected 非虚拟析构函数时抑制 delete-non-virtual-dtor 警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43282826/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com