基类中受保护的非虚拟析构函数

时间:2013-10-25 01:08:09

标签: c++ protected virtual-destructor

我正在尝试了解虚拟析构函数。以下是此页面When to use virtual destructors?

的复制粘贴
  

在这里,您会注意到我没有声明Base的析构函数   虚拟。现在,我们来看看以下片段:

Base *b = new Derived(); // use b 
delete b; // Here's the problem!
     

[...]如果要阻止通过基类指针删除实例,可以使基类析构函数受保护且非虚拟;通过这样做,编译器将不允许您在基类指针上调用delete。

我不明白为什么通过拥有受保护的非虚基类析构函数来阻止删除。编译器是否认为我们试图从基类对象中调用deleteprotected与此有什么关系?

3 个答案:

答案 0 :(得分:9)

C ++标准对此有delete(第5.3.5p10节):

  

对释放函数和析构函数(12.4,12.5)进行访问和模糊控制。

因此,只有有权访问析构函数的代码才能使用delete。由于析构函数是protected,这意味着没有人可以在delete类型的指针上调用Base*。只有子类可以使用析构函数(并且唯一的东西是子类自己的析构函数,作为子对象销毁过程的一部分)。

当然,子类应该创建自己的析构函数public,允许您通过子类类型删除对象(假设它是正确的实际类型)。

注意:实际上,Base的其他成员可以访问delete (Base*)p; {{1}}。但是C ++假定使用这种结构的人不会这样做--C ++访问控制只为你班级以外的代码提供指导。

答案 1 :(得分:5)

delete b;有效执行b->~Base(); deallocate(b);。第一部分 - 调用析构函数 - 如果析构函数不可访问将无法编译(与调用任何其他不可访问的方法失败的方式相同)。

答案 2 :(得分:0)

根据我的理解(基于此page),我们希望在基类中使用非虚拟和受保护的析构函数的唯一情况如下:

  IsOdd *a = new IsOdd;
  delete a;

因此,你只能这样做:

  IsOdd c;

  unary_function *a = new IsOdd;
  delete a;

永远不会:

void f(unary_function *f) {
  delete f; 
  // this function couldn't get compiled because of this delete. 
  // you would have to use the derived class as the parameter 
}

因此,对于非虚拟保护的析构函数,当您尝试使用此编译器时编译器会出错

CASE