在派生指针上显式调用基类析构函数时编译错误

时间:2014-08-19 05:28:16

标签: c++ visual-studio destructor placement-new

就像标题所说的那样。以下设计的示例似乎适用于键盘: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'

显然,这个例子可以很容易地重做以避免这个问题,但我的实际代码库并没有给我任何其他选择。是否有人熟悉Microsoft编译器的这种特殊失败?

3 个答案:

答案 0 :(得分:3)

这不是MSVC中的错误。从标准,§3.4.5[basic.lookup.classref] / p2-3(引用N3936,强调我的):

  

如果类成员访问(5.2.5)中的 id-expression 是    unqualified-id ,[...]

     

如果 unqualified-id ~type-name,则会查找 type-name   在整个 postfix-expression 的上下文中。如果是T的类型   对象表达式是类类型C,类型名称也是   在班级C的范围内查找。 至少有一个查找   应找到一个名称(可能是cv-qualified)T

在您的代码中,TB,查找IBase显然无法找到引用B的名称。因此,您的代码格式不正确。如果g ++接受它,它可能是错误或扩展。

由于听起来实际的B代表的类型在您的实际代码中是“不可言说的”,但IBase可以写,最简单的解决方案就是将b转换为IBase *

答案 1 :(得分:-1)

这是一个已知的错误。至于“为什么”失败,我没有答案。您的示例的解决方法可能是:

B-&GT; I基准::〜广积();

答案 2 :(得分:-1)

自动调用基类析构函数。如果手动调用基类析构函数,那么当对象被销毁时,它将再次调用。