虚関数の役割

2196 ワード

http://www.cnblogs.com/kyleada/archive/2011/05/19/2051184.html
メンバー関数の操作を一般化することができます.ベースクラスのポインタで異なる派生クラスのオブジェクトを指す場合、ベースクラスのポインタが虚メンバー関数を呼び出すと、ベースクラスで定義されたメンバー関数ではなく、本当にオブジェクトを指すメンバー関数が呼び出されます(派生クラスがメンバー関数を書き換えた場合).虚関数でなければ、ベースクラスポインタが指す派生クラスオブジェクトにかかわらず、呼び出し時にベースクラスで定義された関数が呼び出されます.
プログラム1:
#include <iostream>
using namecpace std;

class B0 //  B0  
{ 
    public:
    void display(){cout<<"B0::display()"<<endl;} //      
};

class B1: public B0 
{
    public:
    void display(){cout<<"B1::display()"<<endl;} 
};

class D1: public B1 
{
public:
    void display(){cout<<"D1::display()"<<endl;} 
};

void fun(B0 *ptr) 
{ 
    ptr->display(); //"    ->   "  
}

void main() //   
{ 
    B0 b0; //  B0   
    B1 b1; //  B1   
    D1 d1; //  D1   
    B0 *p; //  B0   
    p=&b0; //B0     B0   
    fun(p);
    p=&b1; //B0     B1   
    fun(p);
    p=&d1; //B0     D1   
    fun(p);
}

実行結果:B 0::display()B 0::display()B 0::display()
プログラム2:
#include <iostream>
using namespace std;

class B0 //  B0  
{
public: //    
    virtual void display() //     
    {
        cout<<"B0::display()"<<endl;
    } 
};

class B1: public B0 //    
{ 
public:
    void display()  
    {  
        cout<<"B1::display()"<<endl;  
    }
};

class D1: public B1 //    
{ 
public:
    void display() 
    {  
        cout<<"D1::display()"<<endl;  
    }
};

void fun(B0 *ptr) //    
{    
    ptr->display();    
}

void main() //   
{ 
    B0 b0,  *p; //         
    B1 b1; //       
    D1 d1; //       
    p=&b0;
    fun(p); //    B0    
    p=&b1;
    fun(p); //     B1    
    p=&d1;
    fun(p); //     D1    
}

実行結果:B 0::display()B 1::display()D 1::display()
虚関数は動的バインドの基礎です.非静的メンバー関数です.クラスの宣言では、関数のプロトタイプの前にvirtualを書きます.virtualはクラス宣言のプロトタイプのみを説明するために使用され、関数実装時には使用できません.継承性があり、ベースクラスには虚関数が宣言され、派生クラスでは説明の有無にかかわらず、同プロトタイプ関数は自動的に虚関数になります.本質:宣言を再ロードするのではなく、上書きします.呼び出し方法:ベースクラスポインタまたは参照により、実行時にポインタが指すオブジェクトのクラスに基づいて、どの関数を呼び出すかが決定されます.