C++中虚函数多态实现的原理刨析

2021-02-22 11:04:30 浏览数 (1)

多态的实现原理刨析

虚函数关键字:virtual 未写virtual关键字前:

代码语言:javascript复制
#include<iostream>
using namespace std;
class Animal {
public:
	
      void speak()
	{
		cout << "动物在说话" << endl;
	}
};
class Cat :public Animal {
public:
	
	 void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
void test()
{
	Animal* a = new Cat;
	a->speak();
}
int main()
{
	test();
	system("pause");
	return 0;
}

输出结果:

添加了virtual关键字后:

代码语言:javascript复制
#include<iostream>
using namespace std;
class Animal {
public:
	//虚函数
	virtual void speak()
	{
		cout << "动物在说话" << endl;
	}
};
class Cat :public Animal {
public:
	//这里的virtual可写可不写,因为继承至Animal,因此如国不写virtual,与父类里面speak同名的函数也会默认为虚函数
	virtual void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
void test()
{
	 //多态发生条件:父类指针或者引用指向子类
	Animal* a = new Cat;
	a->speak();
}
int main()
{
	test();
	system("pause");
	return 0;
}

输出结果:

区别: 代码本意是调用猫类里面的speak函数,但是未在父类speak函数前加virtual关键字时,调用的是父类的speak函数,加了virtual关键字后,调用的是猫类里面的speak函数,这就是多态

在深入探究多态实现原理前,先要理解多态的意思和虚函数实现的条件

多态: 不同类的对象对同一消息的不同响应 注意: 虚函数实现条件 : 1.有继承关系 2.子类重写父类的虚函数 动态多态的使用: 父类的指针或者引用指向子类的对象

多态实现的原理探究:

未写虚函数前:

代码语言:javascript复制
#include<iostream>
using namespace std;
class Animal {
public:
	 void speak()
	{
		cout << "动物在说话" << endl;
	}
};
class Cat :public Animal {
public:
	 void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
void test()
{
	Animal a;
	cout << "空对象a的大小为" << sizeof(a) << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

写了虚函数后:

代码语言:javascript复制
#include<iostream>
using namespace std;
class Animal {
public:
	virtual void speak()
	{
		cout << "动物在说话" << endl;
	}
};
class Cat :public Animal {
public:
	 void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
void test()
{
	Animal a;
	cout << "空对象a的大小为" << sizeof(a) << endl;
}
int main()
{
	test();
	system("pause");
	return 0;
}

未写虚函数前,空对象a的大小为1,写了虚函数后,对象a的大小为4,是因为此时a里面存放了一个vfptr虚函数(表)指针,指针大小无论类型均为4个字节大小 该虚函数指针指向一个虚函数表

当子类未重写父类虚函数时(即cat类里面没有与animal类里面speak同名的函数):

当子类重写了父类虚函数时:

当发生虚函数重写时,子类会把自己的虚函数覆盖掉之前父类的虚函数 因此当父类的指针或者引用指向子类对象的时候,会发生多态,你传入的是cat对象,就去cat的虚函数表中找speak函数的入口地址

0 人点赞