全国咨询/投诉热线:400-618-9090

首页技术文章正文

C/C++培训之继承与虚函数结合过程中的内存释放问题

更新时间:2017-04-14 来源: 黑马程序员C/C++培训学院 浏览量:

我们先来看一个代码,这是在继承与虚函数学生过程中发生的一个错误,涉及到了C++的对象内存的知识,因为这方面知识比较复杂,这里不做过多的介绍,只简单分析一下出错原因。
class Base
{
public:
void fun()
{
Cout << “Base::fun()” << endl;
}
~Base() //虚析构函数
{
cout << ”Base::~Base” << endl;
}
};
class Child:public Base //继承Base类
{
Public:
virtual void fun() //虚函数
{
Cout << “Child:fun()” <<endl;
}
};
int main()
{
Base *p = new Child; //新建一个子类的对象,赋值给一个父类指针
p->fun();
delete p; //通过父类指针释放内存
return 0;
}
VS运行程序时,发生如下错误:
 
通过提示发现,VS提示应该是内存方面的错误。而且对于上面的代码来说,父类中的fun函数不是虚函数,而子类中的fun函数是虚函数,所以p->fun也是会调用父类的fun函数。
那么为什么会出现内存释放的错误呢?重新写一个main函数如下:
int main()
{
Child *c = new Child; //在堆上创建一个子类对象
Base *p = c; //将子类对象指针赋值给一个父类对象指针
cout << c << " " << p << endl; //打印信息
p->fun(); //通过父类指针来调用fun函数
delete p; //通过父类指针释放内存
return 0;
}
再次运行以上代码,结果如下:
 
我们从打印的信息可以看到,Child对象指针值为0x01393FD0,Base对象指针为0x1393FD4,通过打印信息发现两个值并不一样,这样释放内存时产生了错误。
原因如下:
  1. 存在虚函数的类对象中会隐藏了一个虚指针,虚指针存放在对象内存的开始位置,这里子类中有一个虚指针而父类中没有;
  2. 子类中有一块内存布局和父类对象的内存布局是一样的,但是这块内存肯定不是子类对象的起始位置,所以将子类对象指针赋值给一个父类对象指针时,为了操作上不产生错误,会把这块和父类内存布局相同的位置赋值给父类指针,因而发生了内存的偏移;
  3. 在堆上分配的子类对象内存,如上面代码起始地址是0x01393FD0,这里是通过delete父类指针来释放内存,而父类指针的值为0x1393FD4,这样释放内存中检测不是正确的起始位置而发生了错误。
解决方法:
要解决以上问题,就要想办法让子类指针赋值给父类指针时,两个指针的值是一个样,这里我们可以在父类中设置任意一个虚函数(将父类中的fun设置为虚函数或者将父类的析构函数设置为虚函数),这样父类和子类中都有虚指针,赋值时不会发生地址的偏移。
为了防止出现以上错误,我们代码中一定要多加注意。尽量不要在子类中设置虚函数和父类中的普通函数重名,另外还有一个编码小技巧,如果一个类中有虚函数或者纯虚函数时,要将其析构函数设置为虚析构函数,以防发生内存泄漏等问题。



本文版权归黑马程序员C/C++培训学院所有,欢迎转载,转载请注明作者出处。谢谢!
作者:黑马程序员C/C++培训学院
首发:http://www.itheima.com/news/c.html 

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

http://www.itcast.cn/subject/uizly/index.shtml?seozxuids

14天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

20天免费试学

基础班入门课程限时免费

申请试学名额

8天免费试学

基础班入门课程限时免费

申请试学名额

20天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

0天免费试学

基础班入门课程限时免费

申请试学名额

12天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

10天免费试学

基础班入门课程限时免费

申请试学名额
在线咨询 我要报名