1、定义
都有virtual关键字
一个函数为虚函数,该函数可以实现,允许用基类的指针调用子类的同名函数。
一个函数为纯虚函数,该函数不能实现,子类继承这个类必须实现这个函数才能实例化对象。
class A
{
public:
virtual void func();//虚函数
}
class B
{
public:
virtual void func()=0;//纯虚函数
};
void main()
{
A a;
B b; // 不允许,因为类B中有纯虚函数,不能实例化对象
system("pause");
}
2、用法
有纯虚函数的类是抽象类,不能生成对象,只能派生。
他派生的类的纯虚函数没有被改写,那么,它的派生类还是个抽象类。
定义纯虚函数就是为了让基类不可实例化。
虚函数在多态中间的使用: 多态一般就是通过基类的指针在运行时刻调用子类来实现的。
1)有virtual关键字
//定义基类animal,有虚函数born()
class animal
{
public:
void fun1(animal *dog_cat);
virtual void born();
};
void animal::fun1(animal *dog_cat)
{
dog_cat->born();
}
void animal::born()
{
cout<< "This is animal."<<endl;
}
//定义animal的子类dog
class dog: public animal
{
public:
virtual void born();
};
void dog::born()
{
cout<<"This is dog."<<endl;
}
//定义animal的子类cat
class cat:public animal
{
public:
virtual void born();
};
void cat::born()
{
cout<<"This is cat."<<endl;
}
void main()
{
animal a;
dog b;
cat c;
a.fun1(&c);
a.fun1(&b);
system("pause");
}
输出结果:
2)没有virtual关键字
//定义基类animal,无虚函数
class animal
{
public:
void fun1(animal *dog_cat);
void born();
};
void animal::fun1(animal *dog_cat)
{
dog_cat->born();
}
void animal::born()
{
cout<< "This is animal."<<endl;
}
//定义animal的子类dog
class dog: public animal
{
public:
void born();
};
void dog::born()
{
cout<<"This is dog."<<endl;
}
//定义animal的子类cat
class cat:public animal
{
public:
void born();
};
void cat::born()
{
cout<<"This is cat."<<endl;
}
void main()
{
animal a;
dog b;
cat c;
a.fun1(&c);
a.fun1(&b);
system("pause");
}
输出结果:
只要基类的成员函数是虚函数,派生类的同名函数(参数相同,返回值类型相同),函数体不同,不管有没有显式声明virtual都是虚函数。
派生类中virtual关键字可有可无,但是也是虚函数。
#include "stdafx.h"
#include "iostream"
using namespace std;
class A
{
int x;
public:
A(int i) {x=i;}
void show()
{
cout<<"A class show():x="<<x<<endl;
}
virtual void display()
{
cout<<"A class virtual display():x="<<x<<endl;
}
};
class B:public A
{
int y;
public:
B(int i,int j):A(i) { y=j;}
void show()
{
cout<<"B class show(): y="<<y<<endl;
}
void display()//前面有无virtual都可以
{
cout<<"B class virtual display():y="<<y<<endl;
}
};
int main(int argc, _TCHAR* argv[])
{
A a(5),*pa;
B b(10,20);
pa=&b;
pa->show();
pa->display();
system("pause");
return 0;
}
A class show():x=10
B class virtual display():y=20
基类的指针指向派生类的对象,当调用同名的成员函数时:
1)如果在基类中成员函数为虚函数,那么基类指针调用的就是派生类的同名函数。
virtual void display();
可以这么理解:因为该函数是虚的,所以会找真正实现的那个函数,所以调用派生类B中的 B class virtual display.
2)如果基类中成员函数为非虚函数,则调用的是基类的成员函数。
void show(); 因为基类是非虚的,已经完全实现了,所以没有必要再调用派生类的了,就调用基类的A class show()。