码迷,mamicode.com
首页 > 编程语言 > 详细

effective c++ 条款07(为多态基类声明virtual析构函数)整理

时间:2014-11-27 18:38:48      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:effective c++   多态   虚基类析构函数   

一、虚函数表原理

陈皓的一篇blog讲的很透彻:http://blog.csdn.net/haoel/article/details/1948051/

虚函数表可以分为:单一继承无虚函数覆盖、单一继承有虚函数覆盖、多重继承无虚函数覆盖和多重继承和有虚函数覆盖。

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

bubuko.com,布布扣

注意与虚拟继承区分开来

二、多态实现原理

多态则是通过继承、虚函数(virtual)、指针来实现。

class A {
public:
    virtual void func() const {
         coust << “A::func()” << endl;
    }
}

class B : public A {
public: 
    virtual void func() const {
         coust << “B::func()” << endl;
    }
}
使用:
A a* = B();
a->func();
输出:
     B::func()

编译期是不调用任何函数的,编译器编译到a->func()时只是检查有没有语法问题,经过检查没有。编译器并不知道调用的是A版本的func()还是B版本的func(),由于a是一个指向B对象的指针,所以a只知道它指向的是一个A类型(或者能转换成A类型)的对象。通常集成体系就说明了(由于是公有继承)B是一种A。在运行期,a要调用a所指向对象的func()函数,就对它指向的对象下达调用func()的命令,结果a所指向的是一个B对象,这个对象就调用了自己版本(B版)的func()函数,所以输出时B::func()

三、多态带来的内存泄露问题

class TimeKeeper
{
public:
       TimeKeeper();
       ~TimeKeeper();
};

class AtomicClck : public TimeKeeper //原子钟 
{ };
 
class WaterClck : public TimeKeeper  //水钟  
{ }; 

class WristClck : public TimeKeeper //腕表 
{ };

int main()
{ 
     TimeKeeper * ptk = getTimeKeeper() ; //工厂方法获取钟的对象 
     
     delete ptk ;  //由于父类中的析构函数声明为非virtual,所以只会执行父类的析构函数
                   //这样就会造成子类中特有成员内存泄露 
}

书中没说透:delete或者free是按照 基类对象地址+基类大小释放内存的,所以造成子类特有部分的内存泄露。

四、解决方法:为基类析构函数加virtual

class TimeKeeper
{
public:
       TimeKeeper();
       virtual ~TimeKeeper();
};
原理:

子类的虚函数表中既有基类的析构函数,又有子类的析构函数,没有覆盖,所以都会被调用,对应于(一)中的单一继承无覆盖情况。


effective c++ 条款07(为多态基类声明virtual析构函数)整理

标签:effective c++   多态   虚基类析构函数   

原文地址:http://blog.csdn.net/hustyangju/article/details/41547411

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!