C++面试常见问题多态如何实现?虚函数的底层如何实现?

1.黑马程序员多态例子

class Animal
{
public:
	//Speak函数就是虚函数
	//函数前面加上virtual关键字,变成虚函数,那么编译器在编译的时候就不能确定函数调用了。
	virtual void speak()
	{
		cout << "动物在说话" << endl;
	}
};

class Cat :public Animal
{
public:
	void speak()
	{
		cout << "小猫在说话" << endl;
	}
};

class Dog :public Animal
{
public:

	void speak()
	{
		cout << "小狗在说话" << endl;
	}

};
//我们希望传入什么对象,那么就调用什么对象的函数
//如果函数地址在编译阶段就能确定,那么静态联编
//如果函数地址在运行阶段才能确定,就是动态联编

void DoSpeak(Animal & animal)
{
	animal.speak();
}
//
//多态满足条件: 
//1、有继承关系
//2、子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象

void test01()
{
	Cat cat;
	DoSpeak(cat);


	Dog dog;
	DoSpeak(dog);
}


int main() {

	test01();

	system("pause");

	return 0;
}
```


2.多态分为两类

* 静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名
* 动态多态: 派生类和虚函数实现运行时多态

静态多态和动态多态区别:

* 静态多态的函数地址早绑定  -  编译阶段确定函数地址
* 动态多态的函数地址晚绑定  -  运行阶段确定函数地址

早绑定--即编译阶段可确定函数地址   

晚绑定--根据函数传递的参数确定调用什么函数  只有在运行时才可以确定(传猫,猫叫;传狗,狗叫)

3.多态满足条件

* 有继承关系
* 子类重写父类中的虚函数

重载与重写区别:重载--函数名相同 参数不同  ;重写--函数名,返回值类型,参数列表全都相同

4.多态使用条件

* 父类指针或引用指向子类对象

C++面试常见问题多态如何实现?虚函数的底层如何实现?_第1张图片

C++面试常见问题多态如何实现?虚函数的底层如何实现?_第2张图片

5.多态原理

class Animal
{
public:
	virtual void speak()
	{
		cout << "动物在说话" << endl;
	}
};

统计animal类占多少内存空间

 C++面试常见问题多态如何实现?虚函数的底层如何实现?_第3张图片

 sizeof Animal =1         加上virtual之后       sizeof Animal =4; 

原因  :类内部多了指针   vfptr(virtual function pointer)虚函数(表)指针 

 vfptr指向vftabel(虚函数表)

虚函数表:表内记录 虚函数入口地址

1.父类

C++面试常见问题多态如何实现?虚函数的底层如何实现?_第4张图片C++面试常见问题多态如何实现?虚函数的底层如何实现?_第5张图片

2.单继承   

子类继承与父类完全相同内容

C++面试常见问题多态如何实现?虚函数的底层如何实现?_第6张图片C++面试常见问题多态如何实现?虚函数的底层如何实现?_第7张图片

3.当子类重写父类虚函数 

子类中虚函数表内部 替换成子类虚函数地址

C++面试常见问题多态如何实现?虚函数的底层如何实现?_第8张图片C++面试常见问题多态如何实现?虚函数的底层如何实现?_第9张图片

4.当父类指针或引用指向子类对象时 ,发生多态

6.总结

1.虚函数是什么 

   在语法上, 成员函数之前加virtual关键字就让这个函数变成虚函数

   虚函数的作用是实现多态性,即通过基类访问派生类的函数

2.什么是纯虚函数

在虚函数后面添加 =0 ,虚函数就成为纯虚函数,

在很多情况下,基类生成对象很不合理。为了解决这个问题,引入了纯虚函数的概念,将函数定义为纯虚函数,派生类中必须重写实现纯虚函数。对于实现了纯虚函数的子类,该纯虚函数在子类中就变成了虚函数

3.虚函数和纯虚函数区别

  • 虚函数定义形式:成员函数前添加 virtual 关键字,纯虚函数在虚函数后添加 =0 ;
  • 含有纯虚函数的类,称为抽象类;只含有虚函数的类,不能称为抽象类。
  • 虚函数既可以直接使用,也可以被子类重载实现后,以多态的形式调用;而纯虚函数必须被子类重写实现,才能以多态的形式调用,因为纯虚函数在基类中只有声明。否则子类也是抽象类不可实例化
  • 无论虚函数还是纯虚函数,定义中都不能有 static 关键字。因为 static 关键字修饰的内容在编译前就要确定,而虚函数、纯虚函数是在运行时动态绑定的。

4.虚函数表是什么

虚函数表是一个存储着虚函数地址的数据结构;表内记录着虚函数入口地址

5.虚函数表指针是什么

虚函数表指针指向虚函数表;

虚函数的调用是通过查虚函数表来进行的 ;虚函数表中进行查找,则是通过虚指针来调用;

6.虚函数表以及虚函数指针分别是在什么时候创建的

虚函数表的初始化在编译时期,而虚指针的初始化是在构造函数里完成的,而子类虚指针的指向并不是一来就指向子类的那个虚函数表,因为我们都知道子类在调用构造函数时会先调用父类构造函数,这时候虚指针还是指向父类的那个虚表,而当调用子类的构造函数时又会将指向改变为子类的那块表,这就是为什么在父类构造函数里调用虚函数并不能实现多态的原因

内容源自黑马视频以及网络博客总结

54 类和对象-多态-多态的原理剖析_哔哩哔哩_bilibili

C++面向对象总结:虚指针与虚函数表,干货又来了 - 知乎 (zhihu.com)

什么是虚函数?什么是纯虚函数?两者有什么区别?_虚函数和纯虚函数的区别_爱吃煎饺的LinV的博客-CSDN博客

你可能感兴趣的:(1024程序员节,c++,面试)