百度百科关于虚函数的定义:
简单地说,那些被virtual关键字修饰的成员函数,就是虚函数。虚函数的作用,用专业术语来解释就是实现多态性(Polymorphism),多态性是将接口与实现进行分离;用形象的语言来解释就是实现以共同的方法,但因个体差异,而采用不同的策略。
维基百科对于虚函数的定义:
在面向对象程序设计领域,C++、Object Pascal 等语言中有虚函数(英语:virtual function)或虚方法(英语:virtual method)的概念。这种函数或方法可以被子类继承和覆盖,通常使用动态分派实现。这一概念是面向对象程序设计中(运行时)多态的重要组成部分。简言之,虚函数可以给出目标函数的定义,但该目标的具体指向在编译期可能无法确定。
点击传送
继承
数据可以被继承下来,占用内存的一部分;函数的继承 继承的是函数的调用权(子类可以调用父类的函数)。
成员函数可以分为三种:
非虚函数、虚函数和纯虚函数
一个C++例子
应用程序框架是提前就已经写好的,其中的Serialize()方法并没有在基类中实现(当实现应用程序时再实现Serialize()方法)。ps:虽然没有在基类中实现但是基类却使用了这个方法
看主函数,我们可以通过子类去调用父类的方法 OnFileOPen()
写全了就是 CDocument::OnFileOpen(&myDoc); 子类的指针被当作一个参数进行传递,这样在父类的OnFileOpen()函数中执行到Serialize()函数时才可以找到子类对他的实现。
代码:
#include<iostream>
using namespace std;
class CDocument
{
public:
void OnFileOpen()
{
//模拟打开文件的操作
cout << "dialog.." << endl;
cout << "check file status..." << endl;
cout << "open file..." << endl;
Serialize();
cout << "close file..." << endl;
cout << "update all views..." << endl;
}
virtual void Serialize() {};
};
class CMyDoc :public CDocument
{
public:
virtual void Serialize()
{
//只有应用程序本身才知道如何读取自己文件
cout << "CMyDoc::Serialize()" << endl;
}
};
int main()
{
CMyDoc myDoc;
myDoc.OnFileOpen();
}
运行结果:
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.
这种现象在 Java 中叫做向上转型
比如 Animal fish = new Fish(); 这个fish只能调用从父类继承或者重写的方法(丢失了自己独有的方法)。
上面的eat()方法,子类自己实现了就调用自己的,子类没有实现就调用父类给出的。
————————————————————————————————————————————
总结:定义一个函数为虚函数,不代表函数为不被实现的函数。
定义他为虚函数是为了允许用基类的指针来调用子类的这个函数。
定义一个函数为纯虚函数,才代表函数没有被实现。
定义纯虚函数是为了实现一个接口,起到一个规范的作用,规范继承这个类的程序员必须实现这个函数。
推迟实现
一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。
虚函数只能借助于指针或者引用来达到多态的效果。