C++之析构函数与虚函数

一个例子

class Base {
    public:
        Base() {   }
        ~Base() { cout << "Base 析构" << endl; }
    };
    class Derived :public Base {
    public:
        int a;
        Derived() {   };
        ~Derived() { cout << "Derived析构" << endl; };
    };
    Base *p;
    p = new Derived;

    cout << "*p的大小为" << sizeof(*p) << endl;
    cout << "Derived 的大小为" << sizeof(Derived) << endl;
    delete p;

输出结果是:
*p的大小为1
Derived的大小为4
Base 析构

class Base {
    public:
        Base() {   }
        virtual ~Base() { cout << "Base 析构" << endl; }
    };
    class Derived :public Base {
    public:
        int a;
        Derived() {   };
        ~Derived() { cout << "Derived析构" << endl; };
    };
    Base *p;
    p = new Derived;

    cout << "*p 的大小为" << sizeof(*p) << endl;
    cout << "Derived 的大小为" << sizeof(Derived) << endl;
    delete p;

输出结果是:
*p的大小为4
Derived的大小为8
Derived析构
Base 析构

所以: 为什么基类的析构函数要声明成虚函数
第一种情况会发生销毁不完全的情况,因为delete p调用的是声明类型(即基类)的析构函数,所以只能销毁基类对象而无法销毁派生类对象。
当基类的析构函数声明为虚函数,那么派生类的析构函数也是虚函数,此时调用delete p时发生动态绑定,运行时会根据实际类型调用该对象的虚函数。

当然,并不是要把所有类的析构函数都写成虚函数。只有当一个类是基类(即希望被继承)的时候才需要声明成虚函数,因为虚函数的作用是实现多态,而多态是建立在继承的基础上。单一类不能把析构函数写成虚函数,因为会产生额外的开销,比如虚表的创建和虚指针的定义。

关于虚函数和虚表的思考

多态:
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数。这种技术可以让父类的指针有“多种形态”,这是一种泛型技术。所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法。比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议。

先看一段程序:

typedef void(*Fun)(void);
    Base b;
    Fun pFun = NULL;
    cout << "虚函数表地址:" << (int*)(&b) << endl;
    cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(&b) << endl;

    // Invoke the first virtual function 
    pFun = (Fun)*((int*)*(int*)(&b));
    pFun();
    pFun = (Fun)*((int*)*(int*)(&b) + 1);// Base::g()
    pFun();
    pFun = (Fun)*((int*)*(int*)(&b) + 2); // Base::h()
    pFun();

运行结果:

虚函数表地址:0018FDCC
虚函数表 — 第一个函数地址:00B38B34
Base::f
Base::g
Base::h

解释:http://blog.csdn.net/haoel/article/details/1948051/

通过这个示例,我们可以看到,我们可以通过强行把&b转成int *,取得虚函数表的地址,然后,再次取址就可以得到第一个虚函数的地址了,也就是Base::f(),这在上面的程序中得到了验证(把int* 强制转成了函数指针)。通过这个示例,我们就可以知道如果要调用Base::g()Base::h(),其代码如下:

                
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值