c++ - 使析构函数受保护以通过具有虚函数的基类禁用删除调用是个好主意吗
问题描述
我在一个环境中工作,我知道一个抽象基类的所有子类永远不会通过指向这个抽象基类的指针被删除。所以我认为没有必要让这个基类提供虚拟析构函数。因此,我使析构函数受到保护,这似乎可以满足我的要求。
这是一个简化的例子:
#include <iostream>
struct Base
{
virtual void x() = 0;
protected:
~Base() =default;
};
struct Child: Base
{
void x() override
{
std::cout << "Child\n";
}
};
int main()
{
// new and delete are here to make a simple example,
// the platform does not provide them
Child *c = new Child{};
Base *b=c;
b->x();
// delete b; // does not compile, as requested
delete c;
return 0;
}
保护析构函数以防止不必要的基类删除就足够了,还是我在这里错过了一些重要的事情?
解决方案
这是一个好主意 [...]
从安全的角度来看,我的回答是明确的“不”:
考虑子类被再次继承的情况——也许是你以外的其他人这样做。该人可能会忽略您违反了良好实践Base
并假设析构函数Child
已经是虚拟的-并GrandChild
通过指向Child
...的指针删除
为了避免这种情况,你可以
- 使析构函数
Child
再次成为虚拟的——所以最终,无论如何也没有任何收获。 - 或宣布
Child
最终,施加相当多的限制,从任何其他角度来看,这些限制很可能毫无意义。
而且您必须为任何派生类选择其中之一。都是为了避免在对象删除时调用单个虚函数?
你多久会这样做一次?如果对象删除的频率确实是一个问题,那么请考虑再次分配和释放内存的开销。在这种情况下,只分配一次内存(足够大并且适当对齐以容纳您考虑创建的任何对象),执行新的和显式的析构函数调用,最后再次释放内存一次你已经完成了,不再需要它了。这将大大补偿虚函数调用......
推荐阅读
- c++ - 二元运算符实现为静态成员函数
- c - C中的字符串数组:函数内正常,main()中充满垃圾
- flutter - 是否有可以将 ListView.builder 限制在列中的有界小部件?
- java - Java - 为此类的每个现有对象和每个新创建的对象更改类变量的值?
- java - Apache HTTP Java 客户端导致内容长度分隔的消息正文过早结束
- python-3.x - Python字典成绩簿,如何打印漂亮和编辑
- c# - 在 C# 中需要浮点数时以整数形式返回
- java - 如何使用 Spring JPA 仅使用对象的某些部分编写查询
- graph - 扩展对 EWS 基本身份验证的支持
- java - 无法获取 Selenium Java 的对象列表