34 虚函数与多态(一)

来源:互联网 发布:淘宝商品怎么上架视频 编辑:程序博客网 时间:2024/05/23 14:26

静态绑定与动态绑定

静态绑定
绑定过程出现在编译阶段,在编译期就已确定要调用的函数。
动态绑定
绑定过程工作在程序运行时执行,在程序运行时才确定将要调用的函数。
只有通过基类指针或引用调用虚函数才能引发动态绑定

#include <iostream>using namespace std;class Base{public:    virtual void Fun1()    {        cout << "Base::Fun1 ..." << endl;    }    virtual void Fun2()    {        cout << "Base::Fun2 ..." << endl;    }    void Fun3()    {        cout << "Base::Fun3 ..." << endl;    }};class Derived :public Base{public:    /*virtual*/ void Fun1()//如果一个函数在基类中被声明为虚函数,则他在所有派生类中都是虚函数    {        cout << "Derived::Fun1 ..." << endl;    }    /*virtual*/ void Fun2()    {        cout << "Derived::Fun2 ..." << endl;    }    void Fun3()    {        cout << "Derived::Fun3 ..." << endl;    }};int main(void){    Base* p;    Derived d;    p = &d;    p->Fun1(); //Fun1是虚函数,基类指针指向派生类对象,调用的是派生类对象的虚函数    p->Fun2();    p->Fun3(); //Fun3非虚函数,根据p指针实际类型来调用相应类的成员函数    return 0;}

这里写图片描述

#include <iostream>using namespace std;class Base{public:    virtual void Fun1()    {        cout << "Base::Fun1 ..." << endl;    }    virtual void Fun2()    {        cout << "Base::Fun2 ..." << endl;    }    void Fun3()    {        cout << "Base::Fun3 ..." << endl;    }    Base()    {        cout << "Base ..." << endl;    }    //如果一个类要做为多态基类,要将析构函数定义成虚函数    virtual ~Base()    {        cout << "~Base ..." << endl;    }};class Derived :public Base{public:    /*virtual*/ void Fun1()//如果一个函数在基类中被声明为虚函数,则他在所有派生类中都是虚函数    {        cout << "Derived::Fun1 ..." << endl;    }    /*virtual*/ void Fun2()    {        cout << "Derived::Fun2 ..." << endl;    }    void Fun3()    {        cout << "Derived::Fun3 ..." << endl;    }    Derived()    {        cout << "Derived ..." << endl;    }    ~Derived()    {        cout << "~Derived ..." << endl;    }};int main(void){    Base* p;    p = new Derived;    p->Fun1();    delete p;//当通过基类指针删除派生类对象时,如果基类析构函数不是virtual,则派生类析构函数不会调用    return 0;}

这里写图片描述

虚表指针

虚函数的动态绑定是通过虚表指针来实现的
包含虚函数的类头4个字节存放指向虚表的指针

#include <iostream>using namespace std;class Base{public:    virtual void Fun1()    {        cout << "Base::Fun1 ..." << endl;    }    virtual void Fun2()    {        cout << "Base::Fun2 ..." << endl;    }    int data1_;};class Derived :public Base{public:    void Fun2()    {        cout << "Derived::Fun2 ..." << endl;    }    virtual void Fun3()    {        cout << "Derived::Fun3 ..." << endl;    }    int data2_;};typedef void(*FUNC)();int main(void){    cout << sizeof(Base) << endl;    cout << sizeof(Derived) << endl;    Base b;    long** p = (long**)&b;    FUNC fun = (FUNC)p[0][0];    fun();    fun = (FUNC)p[0][1];    fun();    cout << endl;    Derived d;    p = (long**)&d;    fun = (FUNC)p[0][0];    fun();    fun = (FUNC)p[0][1];    fun();    fun = (FUNC)p[0][2];    fun();    return 0;}

输出

object slicing与虚函数

#include <iostream>using namespace std;class CObject{public:    virtual void Serialize()    {        cout << "CObject::Serialize ..." << endl;    }};class CDocument : public CObject{public:    int data1_;    void func()    {        cout << "CDocument::func ..." << endl;        Serialize();    }    virtual void Serialize()    {        cout << "CDocument::Serialize ..." << endl;    }    CDocument()    {        cout << "CDocument" << endl;    }    CDocument(const CDocument& other)    {        cout << "CDocument(const CDocument& other)" << endl;    }};class CMyDoc : public CDocument{public:    int data2_;    virtual void Serialize()    {        cout << "CMyDoc::Serialize ..." << endl;    }};int main(){    CMyDoc mydoc;    CMyDoc* pmydoc = new CMyDoc;    cout << "#1 testing" << endl;    mydoc.func();    cout << "#2 testing" << endl;    ((CDocument*)(&mydoc))->func();    cout << "#3 testing" << endl;    pmydoc->func();    cout << "#4 testing" << endl;    ((CDocument)mydoc).func();//mydoc对象强制转换为CDocument对象,向上转型                             //完完全全将派生类对象转化为了基类对象,调用拷贝构造函数    return 0;}

这里写图片描述

0 0
原创粉丝点击