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.多态使用条件
* 父类指针或引用指向子类对象
5.多态原理
class Animal
{
public:
virtual void speak()
{
cout << "动物在说话" << endl;
}
};
统计animal类占多少内存空间
sizeof Animal =1 加上virtual之后 sizeof Animal =4;
原因 :类内部多了指针 vfptr(virtual function pointer)虚函数(表)指针
vfptr指向vftabel(虚函数表)
虚函数表:表内记录 虚函数入口地址
1.父类
2.单继承
子类继承与父类完全相同内容
3.当子类重写父类虚函数
子类中虚函数表内部 替换成子类虚函数地址
4.当父类指针或引用指向子类对象时 ,发生多态
6.总结
1.虚函数是什么
在语法上, 成员函数之前加virtual关键字就让这个函数变成虚函数
虚函数的作用是实现多态性,即通过基类访问派生类的函数
2.什么是纯虚函数
在虚函数后面添加 =0 ,虚函数就成为纯虚函数,
在很多情况下,基类生成对象很不合理。为了解决这个问题,引入了纯虚函数的概念,将函数定义为纯虚函数,派生类中必须重写实现纯虚函数。对于实现了纯虚函数的子类,该纯虚函数在子类中就变成了虚函数。
3.虚函数和纯虚函数区别
- 虚函数定义形式:成员函数前添加 virtual 关键字,纯虚函数在虚函数后添加 =0 ;
- 含有纯虚函数的类,称为抽象类;只含有虚函数的类,不能称为抽象类。
- 虚函数既可以直接使用,也可以被子类重载实现后,以多态的形式调用;而纯虚函数必须被子类重写实现,才能以多态的形式调用,因为纯虚函数在基类中只有声明。否则子类也是抽象类不可实例化
- 无论虚函数还是纯虚函数,定义中都不能有 static 关键字。因为 static 关键字修饰的内容在编译前就要确定,而虚函数、纯虚函数是在运行时动态绑定的。
4.虚函数表是什么
虚函数表是一个存储着虚函数地址的数据结构;表内记录着虚函数入口地址
5.虚函数表指针是什么
虚函数表指针指向虚函数表;
虚函数的调用是通过查虚函数表来进行的 ;虚函数表中进行查找,则是通过虚指针来调用;
6.虚函数表以及虚函数指针分别是在什么时候创建的
虚函数表的初始化在编译时期,而虚指针的初始化是在构造函数里完成的,而子类虚指针的指向并不是一来就指向子类的那个虚函数表,因为我们都知道子类在调用构造函数时会先调用父类构造函数,这时候虚指针还是指向父类的那个虚表,而当调用子类的构造函数时又会将指向改变为子类的那块表,这就是为什么在父类构造函数里调用虚函数并不能实现多态的原因
内容源自黑马视频以及网络博客总结
54 类和对象-多态-多态的原理剖析_哔哩哔哩_bilibili
C++面向对象总结:虚指针与虚函数表,干货又来了 - 知乎 (zhihu.com)
什么是虚函数?什么是纯虚函数?两者有什么区别?_虚函数和纯虚函数的区别_爱吃煎饺的LinV的博客-CSDN博客