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

C++ 在派生指针上显式调用基类析构函数时发生编译错误,c++,visual-studio,destructor,placement-new,C++,Visual Studio,Destructor,Placement New,正如标题所说。下面的人工示例似乎在codepad上工作:在我的Linux机器上的GCC4.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(){ }

正如标题所说。下面的人工示例似乎在codepad上工作:在我的Linux机器上的GCC4.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);
}
#包括
#包括
IBase类
{
公众:
虚拟~IBase(){}
};
B类:公共IBase
{
公众:
虚拟~B(){}
};
D类:公共B类
{
公众:
虚拟~D(){}
};
int main()
{
void*p=malloc(sizeof(D));
D*D=新的(p)D();
B*B=静态_铸造(d);
b->~IBase();
自由基(p);
}
但是Visual Studio Pro 2012 11.0.61030.00更新4失败,原因是:

main.cpp(30):错误C2300:'B':类没有名为'~IBase'的析构函数。


显然,可以很容易地对示例进行修改以避免该问题,但我的实际代码库没有给我任何其他选项。有人熟悉Microsoft编译器的这一特定故障吗?

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


b->IBase::~IBase()

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

这不是MSVC中的错误。根据标准第3.4.5节[基本.查找.分类参考]/p2-3(引用N3936,强调内容):

如果类成员访问(5.2.5)中的id表达式是 非限定id,[…]

如果非限定id为
~类型名称
,则会查找类型名称 在整个后缀表达式的上下文中。如果 对象表达式是类类型
C
,类型名称也是 在类
C
的范围内查找至少一个查找 应找到一个引用(可能符合cv条件)
T

在您的代码中,
T
B
,查找
IBase
显然找不到引用
B
的名称。因此,您的代码格式不正确。如果g++接受它,它要么是一个bug,要么是一个扩展


因为听起来像是
B
表示的实际类型在您的实际代码中是“无法描述的”,但是
IBase
可以编写,最简单的解决方案是将
B
转换为
IBase*

,从而禁用虚拟调度。@T.C.说得好,我正要修复它,但很明显,虚拟调度是关键所在。@T.C.既然我不能直接在你的帖子下发表评论,你能解释一下你提供的段落吗?@HighTrader基本上是说,当你以
b.~something()的形式写东西时
b
的类型为
b
时,编译器必须能够找到一个名称
某个东西
,它引用了(可能
常量
和/或
volatile
-限定的)
b
。我不确定这是否是MSVC错误;clang也拒绝你的代码。你有什么理由不能将
b
转换为
IBase*
?想想看,这很有道理!谢谢。@T.C是的,这就是接口的用途+1@fauxCoder是的,我错过了。如果没有用户定义的
~b()
,那么
b->~IBase()
是否有效?@RSahu不,问题不是由名称隐藏引起的(如果不定义名称,您会得到隐式的
~b()
)。问题是语言希望您命名的类型与对象的类型匹配。如果对象表达式的类型
T
是类类型
C
的意思,该怎么办?什么时候
T
C
会不同?@RSahu
T
可能不是类类型(在这种情况下,它是一个不做任何事情的伪析构函数调用)。这基本上使编写销毁对象的泛型代码成为可能,而无需确定传入的类型是否为类类型。@RSahu这不是,因为
int
是关键字,但
typedef int;void*buf=malloc(100);int*ip=新(buf)int;ip->~INT()是有效的C++(SO是代码> IP -int::~(int);;见5.2.4[表1]。