1:
abstract 方法 必須 沒有實現, 且必須被繼承類(如果該類不是抽象類的話)實現.
聲明了abstract方法的類必須為abstract類,abstract類可以有其他非抽象方法.
2:
virual方法必須有實現.別不必被繼承類實現.
聲明了virtual方法的類,不必是abstract類
3:
abstract方法只不過是virtual方法的純粹版本,abstract方法也有virtual方法的動態機制(即運行時根據對象引用的具體類型調用相應的方法,也可以說當前引用中調用派生層次最深的方法).
4.
重寫兩種方法,必須在派生類中用override聲明.如果不使用override的話
對於abstract方法:
編譯器會報錯,因為沒有實現抽象類的方法.
對於virtual方法:
相當於覆蓋了virtual方法,使用一個參數列表和返回值,函數名一樣的方法. 該方法不再作為virtual方法,而是普通函數.虛函數搜索時將不再搜索該函數.
此時編譯器會給出警告.因為你用一個函數原型幾乎一模一樣的方法覆蓋了虛方法.如果確實需要這樣做,在方法前加new關鍵字,顯示表明要覆蓋虛方法.
編譯器不再給出警告.
綜上.abstract方法,virual方法與C++中純虛函數,虛函數的概念是一致的.
C++中
1.
純虛函數必須沒有實現
聲明了純虛函數的類一定是抽象基類(ABC)(自動成為,不必額外聲明)
2.
而不是純的虛函數,則必然有實現,否則就成了純虛函數(除非進行方法聲明,又不給出定義,並且沒有 在聲明後面指出這是純虛函數,即"= 0", 這種情況下,任何調用該方法的語句都會導致鏈接錯誤,相當於無用函數)
有虛函數的類,當然可以不必是抽象基類.
3.
純虛函數和虛函數當然都有同樣的動態機制.
所以,結論是:
C#中abstract方法,virual方法與C++中純虛函數,虛函數的概念是一致的.
測試代碼:
abstract public class animal
{
public abstract string get();
public virtual string eat() { return "animal"; }
}
abstract public class waterAnimal : animal
{
//public override string get()
//{
// return ToString();
//}
public override string eat() { return "wateranimal"; }
}
public class fish : waterAnimal
{
public override string get()
{
return ToString();
}
new public string eat() { return "fish"; }
}
public class landAnimal:animal
{
public override string get()
{
return this.ToString();
}
public string get(int a)
{
return "notOverride";
}
}
public class cat:landAnimal
{
public override string get()
{
return this.ToString();
}
}
public class dog : landAnimal
{
public override string get()
{
return this.ToString();
}
}
class Program
{
static void Main(string[] args)
{
animal a = new fish();
Console.WriteLine(a.eat());
//waterAnimal w = new waterAnimal();
//Console.WriteLine(w.eat());
a = new cat();
landAnimal l = new cat();
Console.WriteLine(a.get());
Console.WriteLine(l.get());
a = new dog();
try
{
cat c = a as cat;
c = (cat)a;
}catch(Exception e)
{
Console.WriteLine(e.Message);
}
}
}
哪裡說錯,請糾正.
摘自 zbwzll2的專欄