c++的多态
分为静态多态和动态多态,函数重载和运算符重载属于静态多态,虚函数实现的是动态多态
虚函数允许子类重新定义成员函数,而子类中重新定义父类的方法称为覆盖,或者重写(override)
多态的实现
最常见的方法就是声明基类的指针,让该指针指向任意一个子类对象,由于编写代码的时候,不能确定被调用的是基类的函数还是派生类的函数,所以就采用虚函数。
如果没有声明是虚函数,那么就不会调用子类的函数,只会调用基类的函数。
#include<iostream>
using namespace std;
class A
{
public:
void foo()
{
printf("1\n");
}
virtual void fun()
{
printf("2\n");
}
};
class B : public A
{
public:
void foo() //隐藏:派生类的函数屏蔽了与其同名的基类函数
{
printf("3\n");
}
void fun() //多态、覆盖
{
printf("4\n");
}
};
int main(void)
{
A a;
B b;
A *p = &a;
p->foo(); //输出1
p->fun(); //输出2
p = &b;
p->foo(); //取决于指针类型,输出1
p->fun(); //取决于对象类型,输出4,体现了多态
return 0;
}
纯虚函数
只在基类中声明却没有定义的函数叫做纯虚函数,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” 。
包含纯虚函数的类成为抽象类,抽象类的作用是所以不能定义抽象类的对象。抽象类的主要作用是将有关的操作作为结果接口组织在一个继承层次结构中,由它来为派生类提供一个公共的根,派生类将具体实现在其基类中作为接口的操作。
虚函数允许在派生类中重新定义与基类同名的函数,并且可以通过基类指针或引用来访问基类和派生类的同名函数。虚函数在c++中允许在派生类中重新定义与基类同名的函数,并且可***以通过基类指针或引用来访问基类和派生类的同名函数。
虚函数的核心理念就是通过基类返给您派生类定义的函数,***
使用virtual需注意:
virtual修饰符不能与static、abstract、private或override修饰符一起使用。
在静态属性上的使用virtual修饰符是错误的。
通过使用override修饰符的属性声明,可在派生类中重写virtual继承属性。
override方法:
override方法是提从基类继承的成员的新实现。通过override声明重写的方法称为重写方法。重写方法必须是virtual、abstract或override的。
如果在派生类中的方法前使用带有override的关键字,则派生类的对象将调用该方法,而不调用基类中的方法。
使用override需注意:
override生命不能更改virtual方法的可访问性。
override方法和virtual方法必须具有相同的访问级别修饰符。
不能使用修饰符new、static、virtual或abstract来修饰override方法。
重写属性声明必须指定与继承属性完全相同的访问修饰符、类型和名称,并且被重写的属性必须是virtual、abstract或override的。
虚析构函数
释放的时候回先释放派生类的对象,然后释放基类,
构造的时候,先构造基类,后释放派生类
(a) 如果基类的析构函数不加virtual关键字,那么就是普通析构函数
当基类中的析构函数没有声明为虚析构函数时,派生类开始从基类继承,基类的指针指向派生类的对象时,delete基类的指针时,只会调用基类的析构函数,不会调用派生类的析构函数。
(b) 如果基类的析构函数加virtual关键字,那么就是虚析构函数
当基类中的析构函数声明为虚析构函数时,派生类开始从基类继承,基类的指针指向派生类的对象时,delete基类的指针时,先调用派生类的析构函数,再调用基类中的析构函数。