c++ - Suppress delete-non-virtual-dtor warning when using a protected non-virtual destructor -
i have pure abstract interface class, , derived class implements interface.
struct foo { virtual void dostuff() = 0; }; struct bar : foo { void dostuff() override { } };
my interface class doesn't have virtual destructor.
attempting destruct derived instance using base class pointer therefore undefined behaviour
int main() { foo* f = new bar; f->dostuff(); delete f; }
luckily compiler clever enough catch (with -werror
)
main.cc:15:9: error: deleting object of abstract class type ‘foo’ has non-virtual destructor cause undefined behaviour [-werror=delete-non-virtual-dtor] delete f; ^
i can avoid undefined behaviour ensuring don't attempt delete using base class pointer
int main() { bar* b = new bar; b->dostuff(); delete b; }
unfortunately it's not clever enough pick program formed, , spits out similar error
main.cc:15:9: error: deleting object of polymorphic class type ‘bar’ has non-virtual destructor might cause undefined behaviour [-werror=delete-non-virtual-dtor] delete b; ^
interestingly says might cause undefined behaviour, not will
protected non-virtual destructor:
in one of herb sutter's guru of week's gives following advice:
guideline #4: base class destructor should either public , virtual, or protected , nonvirtual.
so lets make destructor protected nonvirtual.
struct foo { virtual void dostuff() = 0; protected: ~foo() = default; }; struct bar : foo { void dostuff() override { } };
now when accidentally try delete using base class pointer failure
int main() { foo* f = new bar; f->dostuff(); delete f; }
main.cc:5:2: error: ‘foo::~foo()’ protected ~foo() = default; ^ main.cc:17:9: error: within context delete f; ^
great, gives me looking for. let's fix code don't delete using base class pointer
int main() { bar* b = new bar; b->dostuff(); delete b; }
unfortunately same error before
main.cc:17:9: error: deleting object of polymorphic class type ‘bar’ has non-virtual destructor might cause undefined behaviour [-werror=delete-non-virtual-dtor] delete b; ^
question:
how can best of both worlds?
- keep
delete-non-virtual-dtor
error when forget create protected non-virtual destructor, , try delete through base-class pointer - suppress warning when use protected non-virtual destructor, , delete through derived-class pointer
super awesome bonus extra:
- suppress warning when forget use protected non-virtual destructor, correctly deleting through derived-class pointer
marking class final
remove warning.
struct bar final : foo { void dostuff() override { } }; int main() { bar* f = new bar; f->dostuff(); delete f; }
Comments
Post a Comment