面向对象编程有三个特性:封装、继承和多态。
继承和多态指的是什么呢,以下给出了答案。
继承:
1.两个类的关系如果满足a kind of的关系,比如b是a的一种,那么就可以把a设计成基类,b设计成从a继承来的派生类。
2.继承的本质含义是代码的复用,派生类可以继承除基类构造、析构意外其他所有的成员,为派生类所用,派生类只需要实现自己特有的成员即可。
3.基类的指针和引用可以指向派生类对象,但是反过来则不行。
4.两个互为继承关系的类,基类和派生类的同名方法(返回值、函数名、参数列表)相同,并且在基类中,该方法是virtual虚函数,那么这两个方法之间为互为覆盖的关系,否则是隐藏;基类和派生类之间虚函数可以同名覆盖,是c++多态的必备条件之一。
5.c++是支持多重继承的,但是典型的菱形继承等会引发一些问题,导致派生类拥有基类的多份成员变量,和实际情况不符合。解决这个方法需要引入虚继承。
虚函数:
如果派生类继承了有被virtual关键字修饰的函数的基类,被virtual修饰的函数称为虚函数,派生类可以重写该虚函数。如果派生类重写了该虚函数,那么派生类对象调用该方法时调用的就是派生类对象自己实现的方法。如果派生类没有重写该方法,则调用基类的方法。
纯虚函数:
纯虚函数是特殊的虚函数,基类中不能给出这个虚函数的实现方法,派生类必须给出该函数的实现,这种特殊的函数称为纯虚函数,有纯虚函数的类称为抽象类,抽象类不能实例化对象,但是可以定义抽象类的指针或引用,派生类必须重写该方法后才能实例化对象。
多态:
分为静多态和动多态,静多态指的是函数重载和模板,是编译时的多态,动多态是指运行时的多态,指的是继承中虚函数的同名覆盖方法。同时也涉及到早绑定、晚绑定,也就是静态绑定动态绑定,前者指的是编译时就确定使用哪个函数,后者是运行时才知道使用哪个函数,晚绑定基于继承实现,基类指针或者引用指向派生类对象,通过指针引用访问虚函数时,会调用指针所指向的派生类的方法。
如果基类的指针(引用)指向堆上的派生类对象
必须将基类的析构函数写成虚函数,否则会有内存泄露。造成的结果是只调用了基类的析构函数,派生类的未调用。原因是,该指针是Base*类型的指针,Base的析构函数不是虚函数,当delete时,编译时已经确定调用的是Base类的析构。如果将基类的析构写成虚函数,调用delete时,具体调用哪个函数,是运行时才确定的。程序运行时,发现指针指向的是派生类对象,就会先调用派生类的析构,然后调用基类的析构。
构造函数能否写成虚函数:
不能,1.构造函数不能手动调用 2.构造函数用来产生对象,对象产生之后才有vfptr,才能找到vftable,才能找到虚函数指针进行调用,但是没有调用构造函数就没有这些,所以构造函数写成虚函数是矛盾的没有意义的。
内联函数能否写成虚函数:
不能,虚函数必须要有函数指针,但是内联函数在release版本没有函数指针。
Static方法能否写成虚函数:
不能,static函数调用不依赖对象,虚函数多态调用依赖对象中的ptr。
参考:https://blog.youkuaiyun.com/wendy_keeping/article/details/75212860