虚函数:形如 virtual func(param pra);的函数,虚函数体现了多态的特性
纯虚函数: 形如 virtual func(param pra)=0 的函数,含有纯虚函数的类是不能被实例话的,必须由继承它的子类来实现这个纯虚函数,用子类来创建对象。
下面举个栗子:
基类:
class A
{
public:
A();
virtual ~A(){};
void f1()
{
cout << "I am A::f1" << endl;
}
virtual void f2()
{
cout << "I am A::f2" << endl;
}
virtual void f3()=0;
};
子类:
class B : public A
{
public:
B();
virtual ~B(){};
void f1()
{
cout << "I am B::f1" << endl;
}
virtual void f2()
{
cout << "I am B::f2" << endl;
}
virtual void f3()
{
cout << " I am B::f3" << endl;
}
};
主函数:
int main(int argc, char* argv[])
{
// A *m_j1 = new A(); //编译不过,A中有纯虚函数,不能被实例化
A *m_j=new B();
m_j->f1();
m_j->f2();
m_j->f3();
delete m_j;
return 0;
}
输出结果:
I am A::f1
I am B::f2
I am B::f3
I am A::f1:这时才会调用派生类的这个函数,这种特性就是C++里的多态,程序在编译之前,编译器是不知道要调用哪个类的函数,只有在运行的时候,根据指针指向的类型再来决定调用哪个类的函数.这就是动态联编.也叫后期绑定:调用f1函数时,再声明m_j时,m_j的类型是A类型,所以在调用f1时,调用了基类的f1,在运行的时候到底哪个类的该函数被调用关键看调用这个函数的句柄是个什么类型,如果是基类型的话,就会调用基类的这个函数,如果是派生类的话,就会调用派生类的这个函数.m_j这个指针虽然指向了一个派生类对象,但声明这个指针时却是用的基类型来声明的.这就是一个早期绑定,或者叫静态联编,在编译之前调用哪个类的函数已经确定下来了。
I am B::f2:如果想要调用到子类的函数,就要在基类声明函数时加上virtual,就是这里的虚函数,声明成虚函数的函数,这时才会调用派生类的这个函数,这种特性就是C++里的多态,程序在编译之前,编译器是不知道要调用哪个类的函数,只有在运行的时候,根据指针指向的类型再来决定调用哪个类的函数.这就是动态联编.也叫后期绑定。
而基类中f3的声明方式,是为了表明A是一个抽象类,不能被实例化成具体对象,只能用子类来实例化对象,并且子类必须要实现基类的纯虚函数,否则编译报错。