虚函数 (程序语言)
| 本条目需要补充更多来源。(2013年3月21日) |
| 多型原理與實作 |
|---|
虚函数是面向对象程序设计中的一个重要的概念。当从父类中继承的时候,虚函数和被继承的函数具有相同的签名。但是在运行过程中,运行系统将根据对象的型別,自动地选择适当的具体实现运行。虚函数是面向对象编程实现多型的基本手段。
虚函数在设计模式方面扮演重要角色。例如,《设计模式》一书中提到的23种设计模式中,仅5个对象创建模式就有4个用到了虚函数(抽象工厂、工厂方法、生成器、原型),只有單體没有用到。
目录 |
程式範例[编辑]
例如,一個基礎類別 Animal 有一個虛擬函式 eat。子類別 Fish 要實做一個函式 eat(),這個子類別 Fish 與子類別 Wolf 是完全不同的,但是你可以引用類別 Animal 底下的函式 eat() 定義,而使用子類別 Fish 底下函式 eat() 的處理程序。
C++[编辑]
以下程式碼是 C++ 的程式範例。要注意的是,這個範例沒有异常處理的程式碼。尤其是 new 或是 vector::push_back 丟出一個异常時,程式在執行時有可能會出現當掉或是錯誤的現象。
# include <iostream> # include <vector> using namespace std; class Animal { public: virtual void eat() const { cout << "I eat like a generic Animal." << endl; } virtual ~Animal() {} }; class Wolf : public Animal { public: void eat() const { cout << "I eat like a wolf!" << endl; } }; class Fish : public Animal { public: void eat() const { cout << "I eat like a fish!" << endl; } }; class GoldFish : public Fish { public: void eat() const { cout << "I eat like a goldfish!" << endl; } }; class OtherAnimal : public Animal { }; int main() { std::vector<Animal*> animals; animals.push_back( new Animal() ); animals.push_back( new Wolf() ); animals.push_back( new Fish() ); animals.push_back( new GoldFish() ); animals.push_back( new OtherAnimal() ); for( std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) { (*it)->eat(); delete *it; } return 0; }
以下是虛擬函式 Animal::eat() 的輸出:
I eat like a generic Animal. I eat like a wolf! I eat like a fish! I eat like a goldfish! I eat like a generic Animal.
當 Animal::eat() 不是被宣告為虛擬函式時,輸出如下所示:
I eat like a generic Animal. I eat like a generic Animal. I eat like a generic Animal. I eat like a generic Animal. I eat like a generic Animal.
Java[编辑]
在Java语言中, 所有的方法默认都是"虚函数". 只有以关键字 final 标记的方法才是非虚函数. 以下是 Java 中虚方法的一个例子:
import java.util.*; public class Animal { public void eat() { System.out.println("I eat like a generic Animal."); } public static void main(String[] args) { List<Animal> animals = new LinkedList<Animal>(); animals.add(new Animal()); animals.add(new Wolf()); animals.add(new Fish()); animals.add(new OtherAnimal()); for (Animal currentAnimal : animals) { currentAnimal.eat(); } } } public class Wolf extends Animal { public void eat() { System.out.println("I eat like a wolf!"); } } public class Fish extends Animal { public void eat() { System.out.println("I eat like a fish!"); } } public class OtherAnimal extends Animal {}
输出:
I eat like a generic Animal. I eat like a wolf! I eat like a fish! I eat like a generic Animal.
C#[编辑]
在 C# 语言中, 对基类中的任何虚方法必须用 virtual 修饰, 而衍生类中由基类继承而来的重载方法必须用 override 修饰. 一下是 C# 的一个程序实例:
using System; using System.Collections.Generic; namespace ConsoleApplication1 { public class Animal { public virtual void Eat() { Console.WriteLine("I eat like a generic Animal."); } } public class Wolf : Animal { public override void Eat() { Console.WriteLine("I eat like a wolf!"); } } public class Fish : Animal { public override void Eat() { Console.WriteLine("I eat like a fish!"); } } public class GoldFish : Fish { public override void Eat() { Console.WriteLine("I eat like a goldfish!"); } } public class OtherAnimal : Animal { // Eat() method is not overridden, so the base class method will be used. } public class Program { public static void Main(string[] args) { IList<Animal> animals = new List<Animal>(); animals.Add(new Animal()); animals.Add(new Wolf()); animals.Add(new Fish()); animals.Add(new GoldFish()); animals.Add(new OtherAnimal()); foreach (Animal currentAnimal in animals) { currentAnimal.Eat(); } } } }
输出:
I eat like a generic Animal. I eat like a wolf! I eat like a fish! I eat like a goldfish! I eat like a generic Animal.
抽象类和纯虚函数[编辑]
纯虚函数或纯虚方法是一个需要被非抽象衍生类执行的虚函数. 包含纯虚方法的类被称作抽象类; 抽象类不能被直接调用, 一个抽象基类的一个子类只有在所有的纯虚函数在该类(或其父类)内给出实现时, 才能直接调用. 纯虚方法通常只有声明(签名)而没有定义(实现).
作为一个例子, 抽象基类"MathSymbol"可能提供一个纯虚函数 doOperation(), 和衍生类 "Plus" 和 "Minus" 提供doOperation() 的具体实现. 由于 "MathSymbol" 是一个抽象概念, 为其每个子类定义了同一的动作, 在 "MathSymbol" 类中执行 doOperation() 没有任何意义. 类似的, 一个给定的 "MathSymbol" 子类如果没有 doOperation() 的具体实现是不完全的.
虽然纯虚方法通常在定义它的类中没有实现, 在 C++ 语言中, 允许纯虚函数在定义它的类中包含其实现, 这为衍生类提供了备用或默认的行为.
C++[编辑]
在C++语言中, 纯虚函数用一种特别的语法[=0]定义(但 VS 也支持 abstract 关键字:virtual ReturnType Function()abstract;), 见以下示例.
class Abstract { public: virtual void pure_virtual() = 0; };
纯虚函数的定义仅提供方法的原型. 虽然在抽象类中通常不提供纯虚函数的实现, 但是抽象类中可以包含其实现, 而且可以不在声明的同时给出定义[1]. 每个非抽象子类仍然需要重载该方法, 抽象类中实现的调用可以采用以下这种形式:
void Abstract::pure_virtual() { // do something } class Child : public Abstract { virtual void pure_virtual(); // no longer abstract, this class may be // instantiated. }; void Child::pure_virtual() { Abstract::pure_virtual(); // the implementation in the abstract class // is executed }
参考文献[编辑]
- ^ Standard C++ 98 - 10.4/2
- C++ FAQ Lite Copyright © 1991-2006, Marshall Cline.