C++ 虚函数

    1、定义

    C++语言有多态特性,而虚函数正是其表现之一。关于其定义,有以下三个要点:

    (1)必须是基类的非静态成员函数。

    (2)访问权限可以是保护型或公有型。

    (3)函数前需加上关键字virtual。

   

    2、作用

    下面举一例子说明。

    #include <iostream>

    using namespace std;

    class A

    {

    public:

        void Show()

        {

            cout << "A:Show()" << endl;

        }

    };

    class B:public A

    {

    public:

        void Show()

        {

            cout << "B:Show()" << endl;

        }

    };

    void main()

    {

        A a;

        B b;

        A *p = &a;

        p->Show();

        p = &b;

        p->Show();

    }

    上述程序的目的是为了调用类A、类B的Show()函数,但运行结果却是:

    A:Show()

    A:Show()

    造成这一结果的原因是C++的静态编联机制。该机制将指针p与基类A的成员函数Show()连接在一起,无论p指向那个对象,p->Show()调用的总是基类A的成员函数Show()。

    为达到目的,将基类A的成员函数Show()声明为虚函数(派生类B的成员函数Show()虽然没有关键字virtual,但系统仍会判断出派生类B的成员函数Show()是虚函数。关于判断规则,这里不详讲)。这里,关键字virtual提示C++编译器:函数调用p->Show()要在运行时才能确定所要调用的函数(即动态编联)。则运行结果为:

    A:Show()

    B:Show()

这样,通过定义虚函数实现了C++的多态性机制。

 

    3、使用虚函数时需注意一下几点:

    (1)必须首先在基类中定义虚函数。

    (2)实施多态性是通过将基类的指针指向派生类的对象实现的。只有通过基类指针访问虚函数时才能获得运行时的多态性。

    (3)构造函数不能是虚函数。

    (4)析构函数可以是虚函数。基类中的析构函数通常定义为虚函数。

 

    4、应用

    //CThread.h

    #ifndef _CTHREAD_H_

    #define _CTHREAD_H_

    class CThread

    {

    public:

        CThread();

        virtual ~CThread();

    public:

        void StartThread();

        void StopThread(DWORD);

        virtual void Run ();

    private:

        static unsigned int __stdcall ThreadFunction( void *p );

    private:

        HANDLE m_hThread;

    };

    #endif

 

    //CThread.cpp

    #include "CThread.h"

    CThread::CThread():m_hThread(NULL)

    {

    }

    CThread::~CThread()

    {

        StopThread(0);

    }

    void CThread::StartThread()

    {

        if ( m_hThread <= 0 )

        {

            m_hThread = (HANDLE)::_beginthreadex( NULL, 0, ThreadFunction,

                                                 (void *)this, 0, NULL );

                if ( m_hThread <=0 )

                {

                    throw ::GetLastError();

                }

        }

    }  

    void CThread::StopThread( DWORD dwExitCode )

    {

        if ( m_hThread > 0)

        {

            if ( 0 == ::TerminateThread(m_hThread, dwExitCode) )

            {

                throw ::GetLastError();

            }

            m_hThread = NULL;

        }

    }

    unsigned int __stdcall CThread::ThreadFunction( void *p )

    {

        CThread *pThis = (CThread *)p; 

        if ( pThis != NULL)

        { 

            while( 1 )

            {

                pThis ->Run();

            }  

        }

        return 0;

    }

    void CThread::Run()

    {

        cout << "Run CThread::Run()!" << endl;

    }

    上述例子中,线程基类的成员函数Run()定义为虚函数,这样在派生类中Run()有不同的实现,实现不同线程做不同事情的目的。

 

    5、虚析构函数

   基类的析构函数是虚函数,则派生类的析构函数也是虚函数,即使没有加关键字virtual。基类的析构函数通常要定义为虚函数,这是很有必要的,通过下面的例子进行说明。

    #include <iostream>

    using namespace std;

    class A

    {

    public:

        ~A()

        {

            cout << "~A()" << endl;

        };

    };

 

    class B:public A

    {

    public:

        ~B()

        {

            cout << "~B()" << endl;

        };

    };

 

    void main()

    {

        A *p = new B;

        delete p;

    }

    上述代码中,基类A的析构函数不是虚函数。由于静态编联机制,删除指针p时,只会调用基类的析构函数。输出结果是:

    ~A()

    这样的设计思路显然不行。若将基类A的析构函数定义为虚函数(此时派生类B的析构函数也是虚函数),由动态编联得知 delete p 时,程序调用指针p指向的派生类的析构函数,而派生类的析构函数又会自动调用基类的析构函数,这样整个派生类的对象就被完全释放了。运行结果为:

    ~B()

    ~A()

 

   6、纯虚函数

    纯虚函数是一个在基类中说明的虚函数,它在基类中没有定义,但是要求在它的派生类中必须定义自己的版本。即纯虚函数的实现部分在基类中不给出,而在派生类中给出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值