class human
{
public:
human();
~human();
void func();
};
class man:public man
{
public:
man();
~man();
void func();
};
申请内存时,可以使基类指针指向其派生类的对象。
human *h = new human;
human *h = new man;
以上都是可以的。但是此指针只能调用基类被继承的成员。如果基类和子类都有一个同名函数,那么h->func()调用的无论如何都是基类的func。如果想要在指针指向man对象时调用man的func呢,这时则需要虚函数了
class human
{
public:
human();
~human();
virtual void func();
};
class man:public man
{
public:
man();
~man();
virtual void func();
};
当基类中的同名函数设置为virtual时,子类中无论加不加virtual都会自动变成虚函数,当然最好习惯性的加上,便于阅读。
这时基类指针指向基类对象就调用的基类的func,指向子类的对象,调用的就是子类的func。
如果在子类的同名函数后加上override后,如果此函数声明的和基类中不一样,就会报错。
如果在基类的同名函数后加上final后,如果子类有同名函数想要覆盖此函数,则会报错。
纯虚函数:如果基类中同名函数只有声明没有定义,只有子类中有相应的定义,则次函数为纯虚函数,同时基类也成了抽象类,无法实例化。
class human
{
public:
human();
~human();
virtual void func() = 0;
};
class man:public man
{
public:
man();
~man();
virtual void func();
};
由于虚函数的出现,导致基类指针根据不同的对象会调用不同的虚函数,这里成为运行时的动态绑定,只有运行中才能知道该调用哪个,也是动态多态性。静态多态性指的是函数的重载,这在编译过程中就知道该调用哪个,静态绑定。
基类的析构函数一定要定义成虚函数,因为如果不是虚函数,当用指针开辟了指向子类对象的空间时,当delete时,只会调用基类的析构函数,子类的析构函数无法调用。会导致子类中申请空间的变量的空间无法释放,从而内存泄漏