如果在堆区创建一个子类对象,用父类指针接收它(子类中除继承父类中属性,不做属性添加),再delete父类指针,这时堆区中的子类对象会不会删除干尽(就是是否会造成数据泄露)?是否还存在这个子类对象?如果存在占1字节还是不占字节?
从理论上不会造成数据泄露,但肯定会有其他问题得有个具体的例子测试下,如果使用父类指针删除子类对象只调用父类的析构函数,子类对象这个时候还是再得,字节一般不变,跟子类大小一样,你可以在父类中添加一个虚析构函数,让子类的析构函数能用就行
跑这个代码,看类的构造和析构打印输出,就能理解了
#include <iostream>
using namespace std;
class A{
public:
A(){ cout<<"A()"<<endl; }
~A(){ cout<<"~A()"<<endl; }
};
class B{
public:
B(){ cout<<"B()"<<endl; }
virtual ~B(){ cout<<"~B()"<<endl; }
};
class C:public A{
public:
C(){ cout<<"C()"<<endl; }
~C(){ cout<<"~C()"<<endl; }
};
class D:public B{
public:
D(){ cout<<"D()"<<endl; }
~D(){ cout<<"~D()"<<endl; }
};
int main() {
A* a = new C();
B* b = new D();
cout<<"delete A"<<endl;
delete a;
cout<<"delete B"<<endl;
delete b;
return 0;
}
子类对象中除了继承父类中的属性外,还有自己添加的属性,这些属性需要在释放内存时一并释放。
如果不释放这些额外的属性,就会导致数据泄露。因此,在使用完子类对象后,一定要使用delete操作符来释放内存。
答案:
如果在堆区创建一个子类对象,并使用父类指针接收它,那么delete掉父类指针时,虽然子类对象仍然存在,但是它的析构函数不会被调用,会造成内存泄漏。这是因为基类指针只能访问到基类成员,而不能访问派生类新增的成员,所以delete指针所指的内存时,只会调用基类的析构函数,而不会调用派生类的析构函数。因此,为了避免这种情况的发生,应该在父类中将析构函数设置为虚函数,以实现多态。做法如下:
class Person{
public:
virtual ~Person()
{
cout << "~Person" << endl;
}
};
class Student :public Person
{
public:
~Student()
{
cout << "~Student" << endl;
}
};
int main()
{
Person* p = new Student;
delete p;
return 0;
}
在这个例子中,我们定义了一个Person类和一个派生类Student,Person类的析构函数被定义为虚函数。在main函数中,我们用Student类的指针来初始化Person类型的指针,并调用delete删除它。这样做,就能保证在调用delete时,派生类的析构函数也会被调用。
此时,子类对象被正确地删除,不会造成内存泄漏。子类对象占用的堆区空间大小,取决于子类中新增的成员变量与基类的继承关系。如果不新增成员变量,占用的空间大小和基类相同;如果新增成员变量,占用的空间大小就会增加。