在派生指针上显式调用基类析构函数时编译错误
Compile error when explicitly calling the base class destructor on a derived pointer
就像标题所说的那样。下面的人为示例似乎可以在codepad: http://codepad.org/4cgGmvDQ和我的Linux机器上的GCC 4.1.2下工作。
#include<stdlib.h>
#include<new>
class IBase
{
public:
virtual ~IBase(){}
};
class B : public IBase
{
public:
virtual ~B(){}
};
class D : public B
{
public:
virtual ~D(){ }
};
int main()
{
void* p = malloc(sizeof(D));
D* d = new(p) D();
B* b = static_cast<B*>(d);
b->~IBase();
free(p);
}
但是Visual Studio Pro 2012 11.0.61030.00 Update 4失败了:
main.cpp(30): error C2300: 'B' : class does not have a destructor called '~IBase'
这不是MSVC中的错误。出自标准§3.4.5 [basic.lookup]。/p2-3(引用N3936,重点是我的):
如果类成员访问(5.2.5)中的id-表达式是 unqualified-id , [...]
如果unqualified-id为
~type-name
,则查找类型名称在整个后缀表达式的上下文中。如果类型为T
对象表达式的类类型为C
,类型名为在C
类的范围内查找。至少一个查找应该找到一个指向(可能是cv-qualified)T
的名称。
在您的代码中,T
是B
,而查找IBase
显然找不到指向B
的名称。因此,您的代码是病态的。如果g++接受它,它要么是一个bug,要么是一个扩展。
因为听起来B
代表的实际类型在您的实际代码中是"不可说的",但IBase
可以编写,最简单的解决方案是简单地将b
转换为IBase *
。
这是一个已知的bug。至于"为什么"它失败了,我没有答案。您的示例的解决方法可能是:
b -> IBase:: ~ IBase ();
自动调用基类析构函数。如果你手动调用基类析构函数,那么当对象被析构时,它将被第二次调用。
相关文章:
- 使用基类指针创建对象时,缺少派生类析构函数
- 对具有动态分配的内存和析构函数的类对象的引用
- 基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)
- 即使基类和派生类只使用基元数据类型,我是否需要定义虚拟析构函数
- C++11:我可以显式调用基类析构函数来销毁派生类吗
- 为什么我不能使用已删除或私有析构函数分配类的数组?
- 显式默认析构函数禁用类中的默认移动构造函数
- 具有受保护析构函数的类数组的动态分配
- 不带名称、构造函数或析构函数的类
- 我可以从析构函数的类方法调用它吗
- 否,除非函数返回具有抛出析构函数的类
- 析构函数子类中的 c++ 分段错误
- 从没有虚拟析构函数的类继承
- 非平凡的析构函数使类具有非平凡的可构造性
- 是否应该初始化具有未重写的纯虚拟析构函数的类
- 为什么带有用户定义析构函数的类的实例将成员指针设置为零
- 为什么不能对带有析构函数的类进行忆及
- 为什么不为定义了析构函数的类合成move操作呢?
- 在析构函数中将类成员设置为空
- 在第三方软件中派生没有虚析构函数的类