多态&多态对象模型

一、什么是多态

1.定义:多态,顾名思义就是”多种形态”。
2.构成多态的两个条件:
1).虚函数的重写。(子类可以不用写virtual,但父类必须写virtual,一般最好子类和父类都加virtual)
2).父类的指针(或引用)调用虚函数。
3.虚函数的作用主要就是实现多态,简单的说父类的指针或引用调用重写的虚函数的时候,当父类指针或者引用指向父类对象时调用的是父类的虚函数,指向子类对象时调用的是子类的虚函数。
4.虚函数重写后是就有自己相对应的虚函数表,虚函数表是通过一块连续内存来存储虚函数的地址的。虚函数表解决了继承,虚继承的问题。
注:可以构成多态的特例:
**协变也可构成多态。
**把基类的析构函数定义为虚函数,构成多态,调子类和父类的析构函数。
**友元函数不能被继承,静态成员会被继承。

二、多态的对象模型–单继承&多继承

单继承:子类有且只有一个直接父类。

例子:

 #include<iostream>
using namespace std;

class Base
{
public:
    virtual void  func1()
    {
        cout<<"Base::func1"<<endl;
    }
    virtual void  func2()
    {
        cout<<"Base::func2"<<endl;
    }

private:
    int a;
};

class Derive : public Base  
{
public:
    virtual void func1()
    {
        cout<<"Derive::func1()"<<endl;
    }
    virtual void func3()
    {
        cout<<"Derive::func3()"<<endl;
    }
    virtual void func4()
    {
        cout<<"Derive::func4()"<<endl;
    }
private:
    int b;
};

 typedef void (*FUNC)();

 void PrintVTable(int* VTable)
 {
     cout<<"虚表地址"<<VTable<<endl;
     for(int i=0;VTable[i]!=0;i++)
     {
         printf("第%d个虚函数的地址:0x%x,->",i,VTable[i]);
         FUNC f=(FUNC)VTable[i];
         f();
     }
     cout<<endl;
 }
 int main()
 {
     Base b1;
     Derive d1;

     int* VTable1=(int*)(*(int*)&b1);
     int* VTable2=(int*)(*(int*)&d1);

     PrintVTable(VTable1);
     PrintVTable(VTable2);
 }

这里写图片描述
父类Base的虚表:
这里写图片描述
子类Derive的虚表:
这里写图片描述

这里写图片描述

多继承:一个子类直接继承两个以上的父类。

#include<iostream>
using namespace std;
typedef void(*FUNC)();//定义一个函数指针类型
class Base1
{
public:
    virtual void func1()
    {
        cout<<"Base1::func1()"<<endl;
    }
    virtual void func2()
    {
        cout<<"Base1::func2()"<<endl;
    }
private:
    int b1;
};
class Base2
{
public:
    virtual void func1()
    {
        cout<<"Base2::func1()"<<endl;
    }
    virtual void func2()
    {
        cout<<"Base2::func2()"<<endl;
    }
private:
    int b2;
};
class Derive:public Base1,public Base2
{
public:
    virtual void func1()
    {
        cout<<"Derive::func1()"<<endl;
    }
    virtual void func2()
    {
        cout<<"Derive::func2()"<<endl;
    }
    virtual void func3()
    {
        cout<<"Derive::func3()"<<endl;
    }
private:
    int d;
};
void PrintVTable(int* VTable)
 {
     cout<<"虚表地址"<<VTable<<endl;
     for(int i=0;VTable[i]!=0;i++)
     {
         printf("第%d个虚函数的地址:0x%x,->",i,VTable[i]);
         FUNC f=(FUNC)VTable[i];
         f();
     }
     cout<<endl;
 }
int main()
{
    Derive d;
    int* VTable=*((int**)(&d));
    //打印第一个虚表,也就是第一个继承的Base1
    PrintVTable(VTable);
    //Base2的虚表在Base1的后边,因此要给地址+一个Base1的大小
    VTable=(int*)(*((int*)&d+sizeof(Base1)/4));
    PrintVTable(VTable);//打印第二个虚表
    return 0;
}

多重继承中,子类会同时重写多个父类中相同的函数,并且子类将自己的虚函数存放在第一个继承的虚函数表中。子类没有自己的虚表,继承第一个父类的虚表。
这里写图片描述
这里写图片描述
Alt text
这里写图片描述

三、多态的对象模型–菱形继承和菱形虚拟继承

1.菱形继承(钻石继承)

这里写图片描述
代码实现如下:

#include <iostream>
using namespace std;

class B
{
public:
    B()
    {
        cout << "B" << endl;
    }
    ~B()
    {
        cout << "~B()" << endl;
    }
private:
    int b;
};
class C1 :public B
{
public:
    C1()
    {
        cout << "C1()" << endl;
    }
    ~C1()
    {
        cout << "~C1()" << endl;
    }
private:
    int c1;
};
class C2 :public B
{
public:
    C2()
    {
        cout << "C2()" << endl;
    }
    ~C2()
    {
        cout << "~C2()" << endl;
    }
private:
    int c2;
};
class D :public C1, public C2
{
public:
    D()
    {
        cout << "D()" << endl;
    }
    ~D()
    {
        cout << "~D()" << endl;
    }
private:
    int d;
};

int main()
{
    cout << sizeof(B) << endl;
    cout << sizeof(C1) << endl;
    cout << sizeof(C2) << endl;
    cout << sizeof(D) << endl;
    return 0;
}

运行结果:
这里写图片描述
那么如何得到的这个结果,我们在上一篇写到菱形继承的时候已经详细分析过了,这里就不详细说明了,如果想要更深入的理解请参考:http://blog.csdn.net/sakuramyb/article/details/75675079
* 2.菱形虚拟继承*

class Base
{
public:
    void virtual Fun1()
    {
        cout<<"Base::Fun1()"<<endl;
    }
    void virtual Fun2()
    {
        cout<<"Base::Fun2()"<<endl;
    }
public:
    int _b;
};
class Derive1:virtual public Base
{
public:
    void virtual Fun1()
    {
        cout<<"Derive1::Fun1()"<<endl;
    }
    void virtual Fun3()
    {
        cout<<"Derive1::Fun3()"<<endl;
    }
public:
    int _d1;
};
class Derive2:virtual public Base
{
public:
    void virtual Fun1()
    {
        cout<<"Derive2::Fun1()"<<endl;
    }
    void virtual Fun4()
    {
        cout<<"Derive2::Fun4()"<<endl;
    }
public:
    int _d2;
};
class Derive:public Derive1,public Derive2
{
public:
    void virtual Fun1()
    {
        cout<<"Derive::Fun1()"<<endl;//覆盖
    }

    void virtual Fun5()
    {
        cout<<"Derive::Fun5()"<<endl;
    }
public:
    int _d;
};
int main()
{
    Derive d;
    d._b = 2;
    d._d1 = 3;
    d._d2 = 4;
    d._d = 5;
    PrintVTable(*((int*)&d));

}

这里写图片描述
内存分配:
这里写图片描述
这里写图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值