多态
使用场景:将 基类类型的指针或者引用 指向 子类对象,并调用子类的虚函数。
多态(polymorphism)是面向对象编程语言的一大特点,而虚函数是实现多态的机制。其核心理念就是通过基类访问派生类定义的函数。多态性使得程序调用的函数是在运行时动态确定的,而不是在编译时静态确定的。
形成多态必须具备三个条件:
1、必须存在继承关系;
2、继承关系必须有同名虚函数(其中虚函数是在基类中使用关键字Virtual声明的函数,在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数);
3、存在基类类型的指针或者引用,通过该指针或引用调用该类的虚函数;
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// 程序的主函数
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// 存储矩形的地址
shape = &rec;
// 调用矩形的求面积函数 area
shape->area();
// 存储三角形的地址
shape = &tri;
// 调用三角形的求面积函数 area
shape->area();
return 0;
}
Rectangle class area :
Triangle class area :
虚函数
即在类成员方法的声明(不是定义)语句前加“virtual”, 如 virtual void func()
父类的函数为virtual时,子类继承下来的这个函数也是虚函数,这被称为覆写。以前我们一般会推荐大家在子类也为这个函数标记为virtual,提醒我们这是虚函数,而在C++11中,我们更提倡使用override来提醒我们在覆写父类的虚函数
class X
{
public:
virtual void f() {}
};
class Y : public X
{
void f() override {}
};
虚函数虚就虚在所谓“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。
子类如果不提供虚函数的实现,将会自动调用基类的缺省虚函数实现,作为备选方案;
析构函数可以写成虚的,但是构造函数不行:虚函数对应一个vtable,可是这个vtable其实是存储在对象的内存空间的。问题出来了,如果构造函数是虚的,就需要通过 vtable来调用,可是对象还没有实例化,也就是内存空间还没有,无法找到vtable,所以构造函数不能是虚函数。
https://blog.csdn.net/jiadebin890724/article/details/7951520
纯虚函数
在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。
定义含有纯虚函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
纯虚函数,即类成员方法声明为 virtual ReturnType Function()= 0;
且编译器要求在派生类中必须予以重写以实现多态性。所以,用户不能创建类的实例,只能创建它的派生类的实例。
对于纯虚函数,子类必须提供纯虚函数的个性化实现。
定义纯虚函数的目的
- 为派生类强制制定接口。纯虚函数的意义,让所有的类对象(主要是派生类对象)都可以执行纯虚函数的动作,但类无法为纯虚函数提供一个合理的缺省实现。所以类纯虚函数的声明就是在告诉子类的设计者,“你必须提供一个纯虚函数的实现,但我不知道你会怎样实现它”。
- 为了安全,因为避免任何需要明确但是因为不小心而导致的未知的结果,提醒子类去做应做的实现。
- 提高编码效率。
抽象类
称带有纯虚函数的类为抽象类。它是为了抽象和设计的目的为建立的,它处于继承层次结构的较上层。
抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出。
如果派生类中没有重新定义纯虚函数,而只是继承基类的纯虚函数,则这个派生类仍然还是一个抽象类。如果派生类中给出了基类纯虚函数的实现,则该派生类就不再是抽象类了,它是一个可以建立对象的具体的类。
C++ 虚函数、纯虚函数 - Arkin的文章 - 知乎https://zhuanlan.zhihu.com/p/37331092
https://blog.csdn.net/hackbuteer1/article/details/7558868