我用C++编写了以下代码:
#include <iostream>
class Number
{
public:
virtual void foo(){std::cout << "Number foo\n";};
Number (){ std::cout << "Number ctor" << std::endl;}
virtual ~Number(){ std::cout << "Number dtor" << std::endl;}
};
class Complex : public Number
{
public:
virtual void foo(){std::cout << "Complex foo\n";};
Complex (double r=0, double i=0) : _r (r), _i (i)
{ std::cout << "Complex ctor" << std::endl; };
virtual ~Complex(){ std::cout << "Complex dtor" << std::endl;}
private:
double _r,_i;
};
int main()
{
Number *numArr = new Complex [2];
delete [] numArr;
return 0;
}当析构函数被声明为虚拟时,应用程序将因分段错误而退出。当它没有声明为virtual时,就会调用Number类的析构函数(这是显而易见的……)。但是,当析构函数被声明为虚拟的,当我删除复杂类中的doubles时,没有分段错误,析构函数是按照预期的顺序( Complex,Number)调用的,所以我猜问题与对象的大小有关,有人能给我一个解释吗?谢谢,阿米特。
发布于 2011-09-26 02:24:04
我不完全确定,但这就是我所怀疑的.
我想知道这是否与派生类的数组不应该强制转换为基类的数组有关(它们不同,参见:http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.3):delete如何知道它正在删除的对象的大小,以调整numArr[0]和numArr[1]的指针(查找v表并将this传递给d-tor)
显然,标准明确地将其命名为未定义(5.3.5):
如果要删除的对象的动态类型与其静态类型不同,则行为在fined下。
发布于 2011-09-26 02:27:39
Number *numArr = new Complex [2];
delete [] numArr;实际上,delete操作调用的是未定义的行为。
§5.3.5/3表示,
在第一个备选方案(删除对象)中,如果操作数的静态类型与其动态类型不同,则静态类型应为操作数的动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义。如果要删除的对象的动态类型与其静态类型不同,则行为是未定义的。)
它的实际含义是:
Number *object= new Complex();
delete object; //well-defined
//BUT
Number *array = new Complex[N];
delete [] array; //undefined发布于 2011-09-26 02:36:03
在C++中不能有多态数组。数组依赖于指针算法,而指针算法依赖于知道对象大小的编译器。在您的例子中,对第零位以外的任何数组元素的访问都是未定义的。
https://stackoverflow.com/questions/7547538
复制相似问题