虛擬函數與建構子

摘要:虛擬函數與建構子

當一個基礎類別呼叫了一個虛擬函數在不同與語言(C++/C#/Java)中會發生什麼事?

Java會執行衍生類別的虛擬函數,C#必須在衍生類別的覆寫函數中宣告時加入override識別子,

C++無解?(參考C++程式碼最後所列參考資料) 因此在做不同程式語言的程式碼轉換時必須注意此問題

-----C++ code------  

#include <iostream>
using namespace std;
 
class base{
public:
base()
{
cout<<"base default construction"<<endl;
setmethod();
}
 
virtual void setmethod()
{
cout<<"base setmethod"<<endl;
callmethod();
}
 
virtual void callmethod()
{
cout<<"base callmethod"<<endl;
}
 
};
 
class child : public base{
public:
child()
{
cout<<"child construction"<<endl;
}
 
 
void setmethod()
{
cout<<"child setmethod"<<endl;
callmethod();
}
 
void callmethod()
{
cout<<"child callmethod"<<endl;
}
 
};
 
int main()
{
child *test = new child();
int x;
cin>>x;
}
 
/*
Ref:http://www.cis.nctu.edu.tw/chinese/doc/research/c++/C++FAQ-Chinese/c-cppfaq-2.html
 
Q66:若基底類別的建構子呼叫一個虛擬函數,為什麼衍生類別覆蓋掉的那個虛擬函  
     數卻不會被呼叫到?
 
在基底類別 Base 的建構子執行過程中,該物件還不是屬於衍生 Derived 的,所以  
如果 "Base::Base()" 呼叫了虛擬函數 "virt()",則 "Base::virt()" 會被呼叫,  
即使真的有 "Derived::virt()"。  
  
類似的道理,當 Base 的解構子執行時,該物件不再是個 Derived 了,所以當  
Base::~Base() 呼叫 "virt()",則 "Base::virt()" 會被執行,而非覆蓋後的版本  
"Derived::virt()"。  
  
當你想像到:如果 "Derived::virt()" 碰得到 Derived 類別的物件成員,會造成什  
麼樣的災難,你很快就會看出這規則的明智之處。  
*/
 
------C# code-------------
namespace Ineritance_CSharp
{
    public class basec{
        public basec()
   {
   System.Console.WriteLine("base construction");
   setmethod();
   }
 
   public virtual void setmethod()
   {
   System.Console.WriteLine("base setmethod");
   callmethod();
   }
 
   public virtual void callmethod()
   {
   System.Console.WriteLine("base callmethod");
   }
    }
 
    
 
    public class child :  basec
    {
   public child()
   {
   System.Console.WriteLine("child construction");
   }
 
   public override void setmethod()
   {
   System.Console.WriteLine("child setmethod");
   callmethod();
   }
 
        public override void callmethod()
   {
   System.Console.WriteLine("child callmethod");
   }
    }
 
    public class child1 : basec
    {
        public child1()
        {
            System.Console.WriteLine("child construction");
        }
 
        public void setmethod()
        {
            System.Console.WriteLine("child setmethod");
            callmethod();
        }
 
        public void callmethod()
        {
            System.Console.WriteLine("child callmethod");
        }
    }
 
 
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine("---child override method---");
            child test = new child();
            System.Console.WriteLine("----------------------");
            System.Console.WriteLine("child non-override method");
            child1 test1 = new child1();
            System.Console.ReadLine();
        }
    }
}
 
 
--------Java code-----
class basec{
    public basec()
    {
   System.out.println("base construction");
   setmethod();
    }
 
    public void setmethod()
    {
   System.out.println("base setmethod");
   callmethod();
    }
 
    public void callmethod()
    {
   System.out.println("base callmethod");
    }
 
}
 
 
 
class child extends basec
{
    public child()
    {
   System.out.println("child construction");
    }
 
    public void setmethod()
    {
   System.out.println("child setmethod");
   callmethod();
    }
 
    public void callmethod()
    {
   System.out.println("child callmethod");
    }
}
 
public  class Inheritance_Java
{
    public static void main(String[] args)
    {
        //System.out.println("---child override method---");
        child test = new child();
/*
        System.out.println("----------------------");
        System.out.println("child non-override method");
        child1 test1 = new child1();*/
    }
}
 

--


Yotrew.Wing.蛋型.水瓶.U103.Che.KUAS
Yotrew.Wing.M98111XX@MS98.EDU/MIS.CSU
Yotrew.Wing.69241XX@MS92.CS.CCU
Yotrew.Wing.584012XX@89乙.Che.KUAS
Yotrew.Wing.b8803XXX@U92A.CSIE.ISU