C++ 多态(3):多态的实现机制,虚函数表

首先要明确,当通过指针访问类的成员函数时:

1、如果该成员函数是非虚函数,那么编译器会根据指针的类型来找到该函数。即,该指针的类型是哪个类就去调用哪个类的成员函数。

2、如果该成员函数是虚函数,并且派生类中有同类型的成员函数形成覆盖关系,那么编译器会根据指针的指向来找到该函数。即,该指向指向哪个类就去调用哪个类的成员函数。这就是多态的本质。

编译器能够根据指针的指向来找到成员函数,是因为在创建对象时额外添加了一个虚函数表。

如果一个类包含了虚函数,那么在创建该类的对象时就会额外地增加一个数组,数组中的每一个元素都是虚函数的入口地址。不过数组和对象是分开存储的,为了将对象和数组关联起来,编译器还要在对象中安插一个指针,指向数组的起始位置。这里的数组就是虚函数表(Virtual function table),简写为vtable。

我们来看下面的代码:

#ifndef VTABLE_H
#define VTABLE_H
#include <iostream>
#include <string>
using namespace std;

class People{
public:
	People(string name, int age);
	string m_name;
	int m_age;
	
	virtual void display();
	virtual void eating();
};
People::People(string name, int age): m_name(name), m_age(age) {}
void People::display() {
	cout << "People:: name = " << m_name << "  age = " << m_age << endl;
}
void People::eating() {
	cout << "People:: eating..." << endl;
}

class Student: public People{
public:
	Student(string name, int age, double score);
	double m_score;
	
	virtual void display();
	virtual void examing();
};
Student::Student(string name, int age, double score):People(name, age), m_score(score) {}
void Student::display() {
	cout << "Student:: name = " << m_name << "  age = " << m_age << "  score = " << m_score << endl;
}
void Student::examing() {
	cout << "Student:: examing..." << endl;
}

class Senior:public Student{
public:
	Senior(string name, int age, double score, bool hasJob);
	bool m_hasJob;
	
	virtual void display();
	virtual void partying();
};
Senior::Senior(string name, int age, double score, bool hasJob):Student(name, age, score), m_hasJob(hasJob) {}
void Senior::display() {
	cout << "Senior:: name = " << m_name << "  age = " << m_age << "  score = " << m_score;
	if(m_hasJob) cout << " is hasJob." << endl;
	else cout << "no hasJob." <<endl;
}
void Senior::partying(){
	cout << "Senior:: partying..." << endl;
}

#endif

各个类的内存模型如下所示:

可以看到,基类的虚函数在虚函数表中的位置是固定的,派生类新增的虚函数添加到虚函数表的最后,如果派生类中有跟基类中同类型的虚函数且形成覆盖关系,那么新增的这个虚函数会在虚函数表中替换掉基类中原有的虚函数,这样具有覆盖关系的虚函数只会在虚函数表中出现一次。编译器就是根据这个表来找到指针指向的对象的成员函数的。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值