虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的函数!(虚函数在基类中有声明和定义,该基类是可以被实例化的。)
纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数!(纯虚函数在基类中只有声明,没有定义,子类必须实现,该基类无法实例化。)
多态和非多态的区别
实质区别就是函数地址是早绑定还是晚绑定,如果在编译期间就已经确定了函数的调用地址,并生产代码,就是静态的。如果函数的调用地址必须在调用期间才能确定,那么就属于多态,是晚绑定。
多态的作用
封装可以使得代码模块化,继承可以扩展已存在的代码,主要目的是代码重用。
多态的目的是接口重用。
多态的使用
声明一个基类指针,然后使用该指针指向任意一个子类对象,调用相应的虚函数,可以根据子类的不同而实现不同的方法。如果c++没有多态性,那么基类指针调用相应的函数的时候将始终调用到同一个方法。
虚函数实现多态
#include <iostream>
using namespace std;
class Animal
{
public:
virtual void speak()
{
cout << endl << "animal speak";
}
void eat()
{
cout << endl << "animal eating";
}
};
class Dog : public Animal
{
public:
void speak()
{
cout << endl << "wang wang";
}
void eat()
{
cout << endl << "dog eat";
}
};
class Cat : public Animal
{
public:
void speak()
{
cout << endl << "miao miao";
}
void eat()
{
cout << endl << "cat eat";
}
};
int main()
{
Animal* animal = new Animal();
animal->speak();
animal->eat();
animal = new Dog();
animal->speak();
animal->eat();
animal = new Cat();
animal->speak();
animal->eat();
return 0;
}
由于speak()是虚函数,所以在调用的过程当中体现了多态性。
而eat()只是普通函数,所以永远都只会调用父类的函数。
纯虚函数
virtual void function() = 0;
包含纯虚函数的类为抽象类,由于抽象类中包含了未定义的纯虚函数,所以抽象类无法实例化。
继承了抽象类的子类如果没有实现所有的纯虚函数,那么该子类依旧是抽象类。
纯虚函数的作用
虚函数和纯虚函数都能实现多态性。纯虚函数更加类似于接口的抽象,其本身生成对象并不合理。
比如,
动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生
成对象明显不合常理。