我是不是要把C++所有的错误都犯一遍呢?

Timor君 发布于 2012/07/18 06:21
阅读 578
收藏 4

代码一直写崩:

class A
{
public:

   virtual ~A(){}
};

class B : public A
{
private:
   int m_b;
};

int main()
{
    A *p = new B[2];
    delete []p;
    
    return 0;
}

error: core dumped!

什么原因?怎么改?

加载中
2
庄严zhuangyan

c++ 规定 delete [] 不履行多态。“ arrays are not treated polymorphically

delete [] p;这行会出错。

==============

§5.3.5/3 C++03 :In the first alternative (delete object), if the static type of the operand is different from its dynamic type, the static type shall be a base class of the operand’s dynamic type and the static type shall have a virtual destructor or the behavior is undefined. In the second alternative (delete array) if the dynamic type of the object to be deleted differs from its static type, the behavior is undefined.

==============

忘了是看哪一位大拿的书,他比喻到:“鸡蛋是蛋的派生类,但你放鸡蛋的篮子是放蛋的篮子的派生类”。这算是C++一个经久流传的段子了:Is an array of Derived a kind-of array of Base?

==============

解决办法:

一、最好的解决方法是不要有这种设计。因为这种设计基本上都不能工作,不仅仅是虚析构函数。你为基类和派生类再添加一个virtual void foo();,然后试试调用,一样会出错。

二、如果真的需求,请用vector<T*>。来处理,然后写一个固定的foreach 的 operator 来释放。你完全可以把它写在一个模板,以后每遇到这个问题,都祭出这个模板。构造也类似,但因构造函数参数列表不可能固定,所以需要用类工厂的方法来实现(也是定义一个模板,然后为特定的类特化一个。当然,也可以考虑用可变参数等高级用法,需要比较多的技巧)。

三、如果你不喜欢模板,那还是用裸数组,但元素类型使用指针。然后用C的方法是类型转化,再搞成宏。估计也很OK。

四、如果还是觉得上面的讨厌,那就回到纯C。用函数的指针去做虚函数,用malloc来分配内存。也许更爽。


0
Yisen
Yisen
class A的析构函数不是虚的,把vitrual去掉
0
庄严zhuangyan

给个实际代码。为了方便,用的是c++11.

假设有 struct D : public B;

并且基类B定义了虚析构,以及一个虚函数foo(),D也提供了自己的foo实现。

int main()
{
    std::vector<B*> b(10); //10个元素
    std::for_each(b.begin(), b.end(), [](B*& it) { it = new D; }); //循环new。比较讨厌
   
    b[1]->foo();  //不会出错
   
    std::for_each(b.begin(), b.end(), [](B* it) { delete it; });     //循环delete 。比较讨厌。

应该有比这些代码自然和方便的方法。 我用的方法只能说能用而已。
    return 0;
}

0
小熊猫大暴走
小熊猫大暴走
该问题很好,顶起
0
Jooooooker
Jooooooker
delete看的应该是静态类型 而不是动态类型
0
Jooooooker
Jooooooker
噢 肯定是 not应该是
0
Timor君
Timor君
#include <iostream>
using namespace std;
class Base
{
public:
	Base():i(1){}
	int get() {return i;}
private:
	int i;
};

class Derived : public Base
{
public:
	Derived():j(2){}

private:
	int j;
};


int main()
{
	Base b[5];
	Derived d[5];
	for(int i = 0; i < 5; i++)
	{
		b[i] = d[i];
		cout << b[i].get() <<endl;
	}

	cout<<"-----------------------"<<endl;
	
	Base *p = d;
	for(i = 0; i < 5; i++)
		cout << p[i].get() << endl;

	return 0;
}

这段代码也是特别有意思
R
Ryan.li
没什么好奇怪的,你搞清楚c++的内存模型就知道了 d的内存如下[{i,j},{i,j},{i,j},{i,j},{i,j}],使用指针p访问每次移动4个byte, 实际输出是 i,j,i,j,i 这五个,后面的就没访问到
Jooooooker
Jooooooker
还是静态类型和动态类型的问题吧~
0
mallon
mallon
C++本身就是错误
庄严zhuangyan
唉,人来到这个世间,本身就是一个错误。
返回顶部
顶部