Chinaunix首页 | 论坛 | 博客
  • 博客访问: 749409
  • 博文数量: 239
  • 博客积分: 60
  • 博客等级: 民兵
  • 技术积分: 1045
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-22 18:25
文章分类

全部博文(239)

文章存档

2019年(9)

2018年(64)

2017年(2)

2016年(26)

2015年(30)

2014年(41)

2013年(65)

2012年(2)

分类: C/C++

2013-10-17 10:05:37

原文地址:C++虚函数机制解析 作者:zyd_cu

1. 无继承的情况

#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() { cout << "Base::f()" << endl; }
    virtual void g() { cout << "Base::g()" << endl; }
    virtual void h() { cout << "Base::h()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Base *b = new Base;
    cout << *(int*)(&b) << endl; //虚函数表的地址存放在对象最开始的位置

    Fun funf = (Fun)(*(int*)*(int*)b);
    Fun fung = (Fun)(*((int*)*(int*)b + 1));
    Fun funh = (Fun)(*((int*)*(int*)b + 2));


    funf();
    fung();
    funh();


    cout << (Fun)(*((int*)*(int*)b + 3)); // 最后一个位置为0,表明虚函数表的结束

    return 0;
}


注意:在上面这个图中,虚函数表中最后一个节点相当于字符串的结束符,其标志了虚函数表的结束,在Codeblocks下打印为0。 


#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() { cout << "Base::f()" << endl; }
    virtual void g() { cout << "Base::g()" << endl; }
    virtual void h() { cout << "Base::h()" << endl; }
};

class Derive: public Base {
    virtual void f1() { cout << "Derive::f1()" << endl; }
    virtual void g1() { cout << "Derive::g1()" << endl; }
    virtual void h1() { cout << "Derive::h1()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Base *b = new Derive;
    cout << *(int*)b << endl;
    Fun funf = (Fun)(*(int*)*(int*)b);
    Fun fung = (Fun)(*((int*)*(int*)b + 1));
    Fun funh = (Fun)(*((int*)*(int*)b + 2));
    Fun funf1 = (Fun)(*((int*)*(int*)b + 3));
    Fun fung1 = (Fun)(*((int*)*(int*)b + 4));
    Fun funh1 = (Fun)(*((int*)*(int*)b + 5));


    funf(); // Base::f()
    fung(); // Base::g()
    funh(); // Base::h()
    funf1(); // Derive::f1()
    fung1(); // Derive::g1()
    funh1(); // Derive::h1()

    cout << (Fun)(*((int*)*(int*)b + 6));
    return 0;
}


从上表可以发现:

1.  虚函数按照其声明顺序放于表中。

2.  父类的虚函数在子类的虚函数前面。 



3. 继承,虚函数覆盖的情形


#include <iostream>
using namespace std;

class Base {
public:
    virtual void f() { cout << "Base::f()" << endl; }
    virtual void g() { cout << "Base::g()" << endl; }
    virtual void h() { cout << "Base::h()" << endl; }
};

class Derive: public Base {
    virtual void f() { cout << "Derive::f()" << endl; }
    virtual void g1() { cout << "Derive::g1()" << endl; }
    virtual void h1() { cout << "Derive::h1()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Base *b = new Derive;
    cout << *(int*)b << endl;
    Fun funf = (Fun)(*(int*)*(int*)b);
    Fun fung = (Fun)(*((int*)*(int*)b + 1));
    Fun funh = (Fun)(*((int*)*(int*)b + 2));
    Fun fung1 = (Fun)(*((int*)*(int*)b + 3));
    Fun funh1 = (Fun)(*((int*)*(int*)b + 4));


    funf(); // Derive::f()
    fung(); // Base::g()
    funh(); // Base::h()
    fung1(); // Derive::g1()
    funh1(); // Derive::h1()

    cout << (Fun)(*((int*)*(int*)b + 5));
    return 0;
}



从上表可以看出:


1.  覆盖的f()函数被放到了虚表中原来父类虚函数的位置。

2.  没有被覆盖的函数依旧

3.  可通过获取获取成员函数指针来调用成员函数(即使是private类型的),带 来一定安全性的影响。



4. 多继承的情形


#include <iostream>
using namespace std;

class Base1 {
public:
    virtual void f() { cout << "Base1::f()" << endl; }
    virtual void g() { cout << "Base1::g()" << endl; }
    virtual void h() { cout << "Base1::h()" << endl; }
};

class Base2 {
public:
    virtual void f() { cout << "Base2::f()" << endl; }
    virtual void g() { cout << "Base2::g()" << endl; }
    virtual void h() { cout << "Base2::h()" << endl; }
};


class Base3 {
public:
    virtual void f() { cout << "Base3::f()" << endl; }
    virtual void g() { cout << "Base3::g()" << endl; }
    virtual void h() { cout << "Base3::h()" << endl; }
};


class Derive: public Base1,public Base2, public Base3 {
    virtual void f() { cout << "Derive::f()" << endl; }
    virtual void g1() { cout << "Derive::g1()" << endl; }
};

int main()
{
    typedef void (*Fun)();

    Derive d;
    Base1 *b1 = &d;
    Base2 *b2 = &d;
    Base3 *b3 = &d;


    b1->f(); //Derive::f()
    b2->f(); //Derive::f()
    b3->f(); //Derive::f()
    b1->g(); //Base1::g()
    b2->g(); //Base2::g()
    b3->g(); //Base3::g()


    Fun b1fun = (Fun)(*(int*)*(int*)b1);
    Fun b2fun = (Fun)(*(int*)*((int*)b1+1));
    Fun b3fun = (Fun)(*(int*)*((int*)b1+2));

    b1fun(); // Derive::f()
    b2fun(); // Derive::f()
    b3fun(); // Derive::f()

    return 0;
}



从上表可以看出:


1. 每个父类都有自己的虚表。

2. 子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明顺序来判断的)

3. 对于多继承无虚函数覆盖的情况,布局与上图类似(Derive的位置对应Base)

阅读(506) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~