C++三大特性:封装、继承、多态。
封装呢?就是类的概念,把属于这个类的函数、变量与其他隔离起来。
继承呢?派生类可以继承基类的方法。有三种方式继承:public、private、protected。
多态呢?就是今天要说的虚函数的概念。
先看一段代码:
#include<iostream>
#include<vector>
using namespace std;
class Animal{
public:
Animal(){
cout<<"construct Base...."<<endl;
}
virtual void print_class()=0;
virtual ~Animal(){
cout <<"release Animal..."<<endl;
}
};
class horse :public Animal{
public:
horse()
{
cout << "construct horse..."<<endl;
}
virtual void print_class() {
cout <<" get base horse..."<<endl;
}
virtual ~horse()
{
cout << "release horse ..."<<endl;
}
};
class golden_horse:public horse{
public:
golden_horse()
{
cout <<"construct golden_horse..."<<endl;
}
void print_class()
{
cout <<"get golden_horse..."<<endl;
}
~golden_horse()
{
cout <<"release golden_horse..."<<endl;
}
};
int main()
{
Animal *a = new golden_horse();
a->print_class();
delete a;//(1)
horse *b = new horse();
b->print_class();
delete b;
golden_horse *c = new golden_horse();
c->print_class();
delete c;
}
上述代码中基类Animal是一个纯虚函数,里面有个接口print_class(),此基类只是作为一个接口,不能够实例化为对象,只能被其他类继承。
horse继承Animal,并实现了对接口print_class()的重写。
golden_horse继承horse,进一步实现对print_class()的重写。
在主函数中,实例化一个Animal的对象a,但是其指针指向golden_horse的构造函数。所以a的print_class()方法应该是golden_horse的。如果Animal的对象a指向horse,那么其print_class()方法应该是horse的。这就实现了C++中多态的特性,实现一个类,通过执行过程中动态绑定的方式实现对相应方法的调用。
这里需要注意的是,如果基类的析构函数不是虚函数,会发生什么呢?
如果基类的析构函数不是虚函数,那么在析构的时候,只会析构类指针类型的析构函数。类的派生类的析构函数并不会执行,这样的情况下很可能会造成内存泄漏!
针对上面的情况:
假设Animal的析构函数不是虚函数,那么(1)处的输出就是:
release Animal...
而对于horse与golden_horse的析构函数并没有执行。如果基类Animal的析构函数是虚函数,那么(1)处的输出如下:
release golden_horse...
release horse ...
release Animal...