C++实现多态原理探究

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/he_shuai20/article/details/55215181

1. 用virtual关键字申明的函数叫做虚函数,虚函数肯定是类的成员函数。

2. 存在虚函数的类都有一个一维的虚函数表叫做虚表。类的对象有一个指向虚表开始的虚指针。虚表是和类对应的,虚表指针是和对象对应的。

3. 多态性是一个接口多种实现,是面向对象的核心。分为类的多态性和函数的多态性。

4. 多态用虚函数来实现;

5. 纯虚函数是虚函数再加上= 0。

6. 抽象类是指包括至少一个纯虚函数的类。

我们先看一个例子:

#include<iostream>
#include<windows.h>
using namespace std;

class Person
{
	public :
	 void BuyTickets()
	{
		cout << " 买票-全价" << endl;
	}
protected:
	string _name; // 姓名
};
class Student : public Person
{
	public :
	 void BuyTickets()
	{
		cout << " 买票-半价 " << endl;
	}
protected:
	int _num; //学号
};
class Old_Person : public Person
{
public:

	 void BuyTickets()
	{
		cout << "买票-免费" << endl;
	}
private:
	size_t age;
};
int main()
{
	Student s;
	Person* p = &s;
	p->BuyTickets();
	return 0;
}

这个例子的最终输出结果为“买票-全价”。

简单分析一下,我们在这个例子的main函数中,定义了一个Student类的对象s;然后定义了一个Person类的指针变量p;接着把s的地址赋给了p;然后利用该变量调用p->BuyTickets()。所以说最终的输出结果为“买票-全价”。

我们知道p实际指向的是Student类对象,我们希望输出的是儿童买票的结果,这个时候我们使用虚函数就可以实现。下面是我们代码的实现:

#include<iostream>
#include<windows.h>
using namespace std;

class Person
{
	public :
	virtual void BuyTickets()
	{
		cout << " 买票-全价" << endl;
	}
protected:
	string _name; // 姓名
};
class Student : public Person
{
	public :
    virtual void BuyTickets()
	{
		cout << " 买票-半价 " << endl;
	}
protected:
	int _num; //学号
};
class Old_Person : public Person
{
public:

	virtual void BuyTickets()
	{
		cout << "买票-免费" << endl;
	}
private:
	size_t age;
};
int main()
{
	Student s;
	Person* p = &s;
	p->BuyTickets();
	return 0;
}

这个例子输出的结果为:“买票-半价”这也就是根据对象的类型调用了正确的函数。

简单分析一下:编译器在编译时发现Person类中有虚函数的存在,这个时候编译器就会为这个类建立一个虚表(vtable),这歌表是一个一维数组,里面存放的是每一个虚函数的地址,对于这个例子来说,每一个类都会有一个虚表;(即使派生类中无virtual关键字,但只要此派生类所继承的基类有virtual关键字函数,此派生类也会存在);如图所示:


编译器为每个类定义了一个虚表指针(vptr),这个指针指向了对象所属类的虚表;在程序运行时,编译器根据对象类型初始化虚表指针,从而使vptr指向正确的对象所属类的虚表,从而正确调用函数。在上个例子中,p实际指向的是对象类型是Student,所以在调用p->BuyTickets()时,根据Student的虚表中的地址,调用的就是Student的函数。


注意:对于虚函数调用来说,每一个对象内部都有一个虚表指针,该虚表指针被初始化为本类的虚表。所以在程序中,不管你的对象类型如

何转换,但该对象内部的虚表指针是固定的,所以呢,才能实现动态的对象函数调用,这就是C++多态性实现的原理。

总结(基类有虚函数):

1.. 每一个类都有虚表。

2. 虚表可以继承,如果子类没有重写虚函数,那么子类虚表中仍然会有该函数的地址,如果重写了相应的虚函数,那么虚表中的地址就会改

变,指向自身的虚函数实现。如果派生类有自己的虚函数,那么虚表中就会添加该项。





展开阅读全文

没有更多推荐了,返回首页