多态对象模型

1.多态相关概念及使用时需要注意问题。

C++中类的继承中有多态性的概念,所谓的多态就是在类里使用虚函数后,用父类作为对象指针,来正确的调用不同子类或父类来作为相应虚函数。虚基类实际就是继承时使用virtual关键字来定义,为的是让在多重继承时遇到相同的基类时只保留一份,以确定其使用那个类。

2.多态原理。

 当使用基类的指针或引用调用重写的虚函数时,当指向父类调用的就是父类的虚函数,指向子类调用的就是子类的虚函数

3.什么是动态联编,什么静态两边。

动态联编 和 静态联编 都是多态性的一种体现

联编是指一个计算机程序自身彼此关联的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系;按照联编所进行的阶段不同,可分为静态联编和动态联编;

静态联编:
是指联编工作是在程序编译连接阶段进行的,这种联编又称为早期联编;因为这种联编是在程序开始运行之前完成的;

在程序编译阶段进行的这种联编又称静态束定;在编译时就解决了程序中的操作调用与执行该操作代码间的关系,确定这种关系又被称为束定;编译时束定又称为静态束定;

动态联编:
编译程序在编译阶段并不能确切地知道将要调用的函数,只有在程序执行时才能确定将要调用的函数,为此要确切地知道将要调用的函数,要求联编工作在程序运行时进行,这种在程序运行时进行的联编工作被称为动态联编,或动态束定,又叫晚期联编;C++规定:动态联编是在虚函数的支持下实现的;

4.单继承/多继承/菱形继承/菱形虚拟继承。多态场景下对象模型

单继承:当子类与父类构成多态时,子类继承父类的虚表之后,子类虚表里虚函数在内存里的存储情况

多继承:

当一个子类继承多个父类时构成多继承,此时子类会继承这些父类的虚表,子类虚表里虚函数在内存里的存储情况。

菱形继承:

class A  
{  
public:  
    virtual void f1()  
    {  
        cout<<"A::f1()"<<endl;  
    }  
    virtual void f2()  
    {  
        cout<<"A::f2()"<<endl;  
    }  
public:  
    int _a;  
};  


class B:public A  
{  
public:  
    virtual void f1()  
    {  
        cout<<"B::f1()"<<endl;  
    }  
    virtual void f3()  
    {  
        cout<<"B::f3()"<<endl;  
    }  
public:  
    int _b;  


};  


class C:public A  
{  
public:  
    virtual void f1()  
    {  
        cout<<"C::f1()"<<endl;  
    }  
    virtual void f4()  
    {  
        cout<<"C::f4()"<<endl;  
    }  
public:  
    int _c;  
};  


class D:public B,public C  
{  
public:  
    virtual void f1()  
    {  
        cout<<"D::f1()"<<endl;  
    }  
    virtual void f5()  
    {  
        cout<<"D::f5()"<<endl;  
    }  
public:  
    int _d;  
};  


//打印虚函数表  
typedef void(*V_FUNC)();  


void PrintVtable(int* vtable)  
{  
    printf("vtable:%p\n",vtable);  
    int** pvtable=(int**)vtable;  
    for(size_t i=0; pvtable[i]!=0;i++)  
    {  
        printf("vtable[%u]:0x%p->",i,pvtable[i]);  
        V_FUNC f=(V_FUNC)pvtable[i];  
        f();  
    }  
    cout<<"------------------------------------\n";  
}  


void test()  
{  
    D d;  
    d.B::_a=5;  
    d.C::_a=6;  
    d._b=1;  
    d._c=2;  
    d._d=3;  
    PrintVtable(*(int**)&d);  
    PrintVtable(*(int**)((char*)&d+sizeof(B)));  
}  
int main()  
{  
    test();  
    return 0;  

}  

在普通的菱形继承中,处于最先的D类型的对象d,它继承了B,C,并且B,C中分别保存了一份来自继承A的变量;除此之外,B,C还存了虚表指针,通过它可以找到虚表中存的虚函数地址,最后,d对象还存放了自己定义的变量和继承B,C自己定义的变量。 

菱形虚拟继承:

菱形虚拟继承与菱形继承的区别在于,B,C继承A的公共成员a,既不存储在 

B里,也不存储在C里,而是存储在一块公共的部分,而会将B,C相对于这个变量的 
偏移地址(这里的偏移量地址叫做虚基表)存在B,C里。所以说,对象d里的B,C里存放了虚表指针、虚基表指针、自己的变量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值