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

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下的运行结果(打印的虚函数表):

这里写图片描述

多重继承总结:

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值