c++进阶之路02多态的实现与原理
静态联编是指在程序编译连接阶段进行的联编。又被称为早起联编,因为这种联编工作是在程序运行之前完成的。它所支持的多态性称为编译时的多态性。例如:重载函数,子类中的覆盖函数。静态联编的优点是速度快,开销小,但是需要程序员自己预测要使用那些对象。
动态联编是指在程序运行时进行的联编。又被称为晚期联编。需要虚函数来实现。缺点是调用速度慢,但是本身灵活多变。
默认构造函数,该函数的功能是将已知对象的所有数据成员(包括很多,当然包括虚函数表的地址)的指拷贝给对应的对象的所有数据成员。
#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,表明这是虚函数的话,就可以实现动态联编。为什么了?因为有了虚函数,就有了虚函数表,在类中是一个地址。地址里面都是虚函数,并且按顺序放置,父类的虚函数地址在前面。所以赋值后,那个虚函数的地址没有变,但是子类会覆盖父类中的虚函数,因此会调用虚函数表中的函数,与调用的对象无关。
没有理解的同学,请百度虚函数表,上面都讲的详细还有图。
本文出自 “郭俊的博客” 博客,转载请与作者联系!
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。