虛函數(shù)
程序示例
例如,一個基類 Animal 有一個虛函數(shù) eat。子類 Fish 要實做一個函數(shù) eat(),這個子類 Fish 與子類 Wolf 是完全不同的,但是你可以引用類別 Animal 底下的函數(shù) eat() 定義,而使用子類 Fish 底下函數(shù) eat() 的進(jìn)程。
C++
以下代碼是 C++ 的程序示例。要注意的是,這個示例沒有異常處理的代碼。尤其是 new 或是 vector::push_back 丟出一個異常時,程序在運行時有可能會出現(xiàn)當(dāng)?shù)艋蚴清e誤的現(xiàn)象。
類別 Animal 的區(qū)塊圖
# include # include usingnamespacestd;classAnimal{public:virtualvoideat()const{cout<<"I eat like a generic Animal."<<endl;}virtual~Animal(){}};classWolf:publicAnimal{public:voideat()const{cout<<"I eat like a wolf!"<<endl;}};classFish:publicAnimal{public:voideat()const{cout<<"I eat like a fish!"<<endl;}};classGoldFish:publicFish{public:voideat()const{cout<<"I eat like a goldfish!"<<endl;}};classOtherAnimal:publicAnimal{};intmain(){std::vectoranimals;animals.push_back(newAnimal());animals.push_back(newWolf());animals.push_back(newFish());animals.push_back(newGoldFish());animals.push_back(newOtherAnimal());for(std::vector::const_iteratorit=animals.begin();it!=animals.end();++it){(*it)->eat();delete*it;}return0;}
以下是虛函數(shù) Animal::eat() 的輸出:
當(dāng) Animal::eat() 不是被宣告為虛函數(shù)時,輸出如下所示:
Java
在Java語言中, 所有的方法默認(rèn)都是"虛函數(shù)". 只有以關(guān)鍵字 final 標(biāo)記的方法才是非虛函數(shù). 以下是 Java 中虛方法的一個例子:
importjava.util.*;publicclassAnimal{publicvoideat(){System.out.println("I eat like a generic Animal.");}publicstaticvoidmain(String[]args){Listanimals=newLinkedList();animals.add(newAnimal());animals.add(newWolf());animals.add(newFish());animals.add(newOtherAnimal());for(AnimalcurrentAnimal:animals){currentAnimal.eat();}}}publicclassWolfextendsAnimal{publicvoideat(){System.out.println("I eat like a wolf!");}}publicclassFishextendsAnimal{publicvoideat(){System.out.println("I eat like a fish!");}}publicclassOtherAnimalextendsAnimal{}
輸出:
C#
在 C# 語言中, 對基類中的任何虛方法必須用 virtual 修飾, 而派生類中由基類繼承而來的重載方法必須用 override 修飾. 一下是 C# 的一個程序?qū)嵗?
usingSystem;usingSystem.Collections.Generic;namespaceConsoleApplication1{publicclassAnimal{publicvirtualvoidEat(){Console.WriteLine("I eat like a generic Animal.");}}publicclassWolf:Animal{publicoverridevoidEat(){Console.WriteLine("I eat like a wolf!");}}publicclassFish:Animal{publicoverridevoidEat(){Console.WriteLine("I eat like a fish!");}}publicclassGoldFish:Fish{publicoverridevoidEat(){Console.WriteLine("I eat like a goldfish!");}}publicclassOtherAnimal:Animal{// Eat() method is not overridden, so the base class method will be used.}publicclassProgram{publicstaticvoidMain(string[]args){IListanimals=newList();animals.Add(newAnimal());animals.Add(newWolf());animals.Add(newFish());animals.Add(newGoldFish());animals.Add(newOtherAnimal());foreach(AnimalcurrentAnimalinanimals){currentAnimal.Eat();}}}}
輸出:
抽象類和純虛函數(shù)
純虛函數(shù)或純虛方法是一個需要被非抽象的派生類覆蓋(override)的虛函數(shù). 包含純虛方法的類被稱作抽象類; 抽象類不能被直接實例化。 一個抽象基類的一個子類只有在所有的純虛函數(shù)在該類(或其父類)內(nèi)給出實現(xiàn)時, 才能直接實例化. 純虛方法通常只有聲明(簽名)而沒有定義(實現(xiàn)),但有特例情形要求純虛函數(shù)必須給出函數(shù)體定義.
作為一個例子, 抽象基類"MathSymbol"可能提供一個純虛函數(shù) doOperation(), 和派生類 "Plus" 和 "Minus" 提供doOperation() 的具體實現(xiàn). 由于 "MathSymbol" 是一個抽象概念, 為其每個子類定義了同一的動作, 在 "MathSymbol" 類中執(zhí)行 doOperation() 沒有任何意義. 類似的, 一個給定的 "MathSymbol" 子類如果沒有 doOperation() 的具體實現(xiàn)是不完全的.
雖然純虛方法通常在定義它的類中沒有實現(xiàn), 在 C++ 語言中, 允許純虛函數(shù)在定義它的類中包含其實現(xiàn), 這為派生類提供了備用或默認(rèn)的行為. C++的虛基類的虛析構(gòu)函數(shù)必須提供函數(shù)體定義,否則鏈接時(linking)在析構(gòu)該抽象類的派生實例對象的語句處會報錯。
C++
在C++語言中, 純虛函數(shù)用一種特別的語法[=0]定義(但 VS 也支持 abstract 關(guān)鍵字:virtual ReturnType Function()abstract;), 見以下示例.
classAbstract{public:virtualvoidpure_virtual()=0;};
純虛函數(shù)的定義僅提供方法的原型. 雖然在抽象類中通常不提供純虛函數(shù)的實現(xiàn), 但是抽象類中可以包含其實現(xiàn), 而且可以不在聲明的同時給出定義. 每個非抽象子類仍然需要重載該方法, 抽象類中實現(xiàn)的調(diào)用可以采用以下這種形式:
voidAbstract::pure_virtual(){// do something}classChild:publicAbstract{virtualvoidpure_virtual();// no longer abstract, this class may be// instantiated.};voidChild::pure_virtual(){Abstract::pure_virtual();// the implementation in the abstract class // is executed}
參考文獻(xiàn)
C++ FAQ LiteCopyright ? 1991-2006, Marshall Cline.
免責(zé)聲明:以上內(nèi)容版權(quán)歸原作者所有,如有侵犯您的原創(chuàng)版權(quán)請告知,我們將盡快刪除相關(guān)內(nèi)容。感謝每一位辛勤著寫的作者,感謝每一位的分享。
- 有價值
- 一般般
- 沒價值
{{item.userName}} 舉報
{{item.time}} {{item.replyListShow ? '收起' : '展開'}}評論 {{curReplyId == item.id ? '取消回復(fù)' : '回復(fù)'}}
{{_reply.userName}} 舉報
{{_reply.time}}