探索多态和多态对象模型—单一继承&多重继承

来源:互联网 发布:淘宝top api易语言sdk 编辑:程序博客网 时间:2024/05/16 00:54

1.什么是多态?

谈到多态,我们必须首先了解一下什么是虚函数。虚函数:在类的成员函数前加virtual关键字,把这个成员函数称为虚函数。
多态需满足两个条件:

子类的虚函数须覆盖(重写)父类的虚函数;(协变例外)
当使用基类的指针或引用调用重写的虚函数时,指向基类对象就调用基类的虚函数,指向派生类的对象就调用派生类的虚函数。

注:多态只与对象有关,与类型无关。
扩充:虚函数重写(覆盖):当派生类中定义的虚函数和基类中定义的虚函数完全相同的时候,则称派生类中的虚函数重写了基类中的虚函数。
协变:

class A{public:    virtual A* func()---virtual A& func()    {        return this;---return *this;    }};class B{public:    virtual B* func()---virtual B& func()    {        return this;---return *this;    }};

2.多态的对象模型
单一继承模型

typedef void(*FUNC) ();class First{public:    First()        :_f(1){}    virtual void f(){ cout << "First::f()" << endl; }    virtual void f1(){ cout << "First::f1()" << endl; }public:    int _f;};class Second : public First{public:    Second()        :_s(2){}    virtual void f(){ cout << "Second::f()" << endl; }    virtual void f2(){ cout << "Second::f2()" << endl; }    virtual void f3(){ cout << "Second::f3()" << endl; }public:    int _s;};void Print(int *Vfptr){    cout << "虚表地址" << Vfptr << endl;    for (int i = 0; Vfptr[i] != 0; ++i)    {        FUNC f = (FUNC)Vfptr[i];        cout << "[" << i << "]" << endl;        f();    }    cout << endl;}int main(){    First f;    Second s;    int *Vfptr1 = (int*)(*(int*)&f);    int *Vfptr2 = (int*)(*(int*)&s);    Print(Vfptr1);    Print(Vfptr2);    system("pause");    return 0;}

这里写图片描述
单一继承总结:

虚函数表一般放在最前面;
成员变量根据会根据继承关系按先后顺序排列;
当有虚函数覆盖时,派生类的虚函数会将虚函数表中的基类虚函数替换;
虚函数表最后一个为0/NULL。

多重继承模型:

这里写图片描述

class B1{public:    B1()    :_b1(1){}    virtual void b(){ cout << "B1::b()" << endl; }    virtual void b1(){ cout << "B1::b1()" << endl; }public:    int _b1;};class B2 {public:    B2()    :_b2(2){}    virtual void b(){ cout << "B2::b()" << endl; }    virtual void b2(){ cout << "B2::b2()" << endl; }    virtual void b3(){ cout << "B2::b3()" << endl; }    virtual void b4(){ cout << "B2::b4()" << endl; }public:    int _b2;};class D : public B1 , public B2{public:    D()    :_d(3){}    virtual void b(){ cout << "D::b()" << endl; }    virtual void b1(){ cout << "D::b1()" << endl; }    virtual void b3(){ cout << "D::b3()" << endl; }    virtual void b5(){ cout << "D::b5()" << endl; }public:    int _d;};typedef void(*FUNC) ();//函数指针void Print(int *Vfptr){    cout << "虚表地址" << Vfptr << endl;    for (int i = 0; Vfptr[i] != 0; ++i)    {        FUNC f = (FUNC)Vfptr[i];        cout << "[" << i << "]" << endl;        f();    }    cout << endl;}int main(){    D d;    int *Vfptr1 = (int*)(*(int*)&d);//B2的虚函数表在B1虚函数表的下面,跳过B1虚函数才可以打印出B2的虚函数表    int *Vfptr2 = (int*)(*((int*)&d+sizeof(B1)/4));    Print(Vfptr1);    Print(Vfptr2);    system("pause");    return 0;}

D继承后B1,B2后,D类的实例化对象模型:

这里写图片描述

在VS2013下的运行结果(打印的虚函数表):

这里写图片描述

多重继承总结:

派生类会继承每个基类的虚函数表;
派生类的成员函数会放在第一个基类的虚函数表中;
成员变量的存储顺序是按照继承先后顺序存储;
派生类中有和基类中相同的虚函数,基类的虚表会被改变。

原创粉丝点击