c++多态性及多态的内部实现(翁恺c++公开课[23-24])

多态是在父类函数的前面加上 “virtual” 关键字,使子类与父类同名的函数产生一种联系;

多态会用到两个特性:向上造型、动态绑定

向上造型是指:拿一个子类对象当作父类来看待,比如下边代码中的子类Ellipse对象ell当作父类Shape对象来看待;

动态绑定:当我要调用一个函数的时候,运行的时候才知道要调用哪个函数,编译的时候是不确定的;

class Shape
{
public:
    Shape();
    virtual ~Shape();  //析构为什么会有虚函数
    virtual void render();
    void move(const XYPos&);
    virtual void resize();
protected:
    XYPos center;
};

class Ellipse : public Shape
{
public:
    Ellipse(float maj, float minr);
    virtual void render();     //will define own
protected:
    float major_axis,minor_axis; 
};

class Circle : public Ellipse
{
public:
    Circle(float radius) : Ellipse(radius, radius) {}
    virtual void render();
};
...
void render(Shape* p)
{
    p->render();        //这里会根据传进来的形参类型,来决定调用哪个类的render函数
}
void func()
{
    Ellipse ell(10, 20);
    ell.render();
    Circle circ(40);
    circle.render();
    render(&ell);        // 这里是调用的Ellipse的render函数
    render(&circ);      //这里是调用了Circle的render函数
}

virtual写在函数前面的作用:如果使用指针或引用调用此函数时,只有在编译的时候才知道选哪个类的render函数去调用,我们这里说void render(Shape *p)中的p指针时多态指针,p的形态是不定可能是基类也可能是某一个子类。

多态的实现:

所有的 有virtual的类的对象最头上都会又一个叫vptr的指针指向一个虚函数表(vtable);

这张vtable虚表里的内容是什么呢,是类的所有的有virtual的函数的地址,这张表属于这个类,而不是类的每个对象,这就是说所有对象的vptr的值都是一样的,指向同一个地址;

下面两个图是内存模型:在每个类的虚函数表中发生继承的virtual函数会被替换成自己的,结合上边的代码render(&ell);此时ell->render()时,ell指针的地址+2就是要调用的函数的地址了,所以说,虚函数的实现并不是去判断这个指针是什么类型,这样做的好处就是大大的提升效率。

 下面看一些面试官比较喜欢考的题,这种题往往会各种赋值,以达到把你绕晕的效果,这里我们只要记住它的本质就好,顺着本质去捋,再怎么绕也能轻松解开。

考点

  1. 多态的本质就是vtable(虚函数表),采用指针+n的方式调用虚函数
  2. 只有通过指针或引用的方式才能去调用 ,通过对象 点 的方式是不会触发多态机制的

目录

  1. c++(翁恺浙大公开课) 笔记0
  2. static在cc++中的作用(翁恺c++公开课[28-29]学习笔记)
  3. c++对象初始化(翁恺c++公开课[10])
  4. c++构造函数的初始化列表(翁恺c++公开课[13])
  5. c++继承:公有、私有、保护
  6. c++子类父类关系(翁恺c++公开课[15-16]学习笔记)
  7. c++拷贝构造函数(翁恺c++公开课[26-27]学习笔记)
  8. c++多态性及多态的内部实现(翁恺c++公开课[23-24])
  9. c++中的运算符重载operator1(翁恺c++公开课[30]学习笔记)
  10. c++中的运算符重载operator2(翁恺c++公开课[31-33]学习笔记)
  11. c++模板(翁恺c++公开课[34-35]学习笔记)
  12. 最好不要在头文件中写函数定义
原文地址:https://www.cnblogs.com/go-ahead-wsg/p/12210835.html