c++进阶之路02多态的实现与原理

  1. 静态联编是指在程序编译连接阶段进行的联编。又被称为早起联编,因为这种联编工作是在程序运行之前完成的。它所支持的多态性称为编译时的多态性。例如:重载函数,子类中的覆盖函数。静态联编的优点是速度快,开销小,但是需要程序员自己预测要使用那些对象。

  2. 动态联编是指在程序运行时进行的联编。又被称为晚期联编。需要虚函数来实现。缺点是调用速度慢,但是本身灵活多变。

  3. 默认构造函数,该函数的功能是将已知对象的所有数据成员(包括很多,当然包括虚函数表的地址)的指拷贝给对应的对象的所有数据成员。

#include <iostream>

const double P = 1.0;

using namespace std;

class People

{

    public:

       People(){};

       double age()const{return 0.0;}

};

class Student

{

    public:

       Student(int i){R = i;}

       double age()const{return P*R*R;}         //覆盖

    protected:

       int R;

}

void func(People& s)

{

    cout<<s.age()<<endl;                            

}

int main()

{

    Peopel people;

    Student student;

    func(people);                    //结果为0.0

    func(student);                   //结果为0.0

    return 0;
}

为什么没有实现多态了,因为静态联编,在编译的时候就要确定调用的函数。将student赋值给People会怎么赋值了,见上面第三条,没有将student的age()函数的地址传给people,(因为子类全部继承父类的信息,还扩充了,赋给父类时,只是把继承的信息全部留下了,扩充的信息全部丢失了)所以都是调用的people的age()方法。所以静态联编的缺点就是需要程序员自己指定是哪个对象调用方法,没有灵活性。



如果将age()方法前面加上关键字virtual,表明这是虚函数的话,就可以实现动态联编。为什么了?因为有了虚函数,就有了虚函数表,在类中是一个地址。地址里面都是虚函数,并且按顺序放置,父类的虚函数地址在前面。所以赋值后,那个虚函数的地址没有变,但是子类会覆盖父类中的虚函数,因此会调用虚函数表中的函数,与调用的对象无关。


没有理解的同学,请百度虚函数表,上面都讲的详细还有图。


本文出自 “郭俊的博客” 博客,转载请与作者联系!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。