1. C++ 重载和重写的区别以及实现方式
- 🐧①
C++
重载:在相同作用域内,函数名相同,参数个数、参数类型、参数顺序不同。 - 1)重载时在编译时实现的;
- 2)重载通过函数的参数列表来区分不同的函数;
- 3)不能通过返回值来判断;
- 🐧②
C++
重写:不在同一个作用域,子类继承时,需要重写父类的虚函数,以实现运行时多态。 - 1)不在同一个作用域内;
- 2)函数名相同、参数相同、返回值相同;
- 3)基类虚函数必须使用
virtual
关键字修饰,不能用static
关键字修饰; - 4)重写后的访问权限可以不同;
- 5)重写是子类中重新定义父类的虚函数,使得子类提供不同的实现;
2. C++ 多态是如何实现的
- 🍎
C++
中的多态性是通过虚函数和虚函数表来实现的。多态性允许在基类类型的指针或者引用上调用派生类对象的函数,以便在运行时选择正确的函数实现。
①🐧基类声明虚函数:在基类中声明虚函数,使用 virtual
关键字修饰,以便派生类可以重写这些函数。
②🐧派生类重写虚函数:在派生类中重写基类中声明的虚函数,使用override
关键字修饰。
③🐧使用基类类型的指针或者引用指向派生类对象。
多态的核心是动态绑定(或称为运行时绑定)。通过基类指针或引用,代码可以处理不同类型的派生类对象,而不需要知道对象的具体类型。
④🐧调用虚函数:通过基类指针或引用调用虚函数。在运行时,系统会根据对象的实际类型来选择调用正确的函数实现。
⑤🐧虚函数表:编译器在对象的内存布局中维护了一个虚函数表,其中存储了指向实际函数的指针。这个表在运行时用于动态查找调用的函数。
每个类会有一张虚函数表记录这个类需调用的函数。
每个类的实例对象都有一个虚函数指针指向这个表。
3. 虚函数和虚函数表
🐧虚函数:
C++
中的虚函数的作用主要是实现了多态的机制。虚函数允许在派生类中重新定义基类中定义的函数,使得基类的指针或者引用调用的函数在运行时根据实际对象类型来确定。这样的机制被称为动态绑定或者是运行时多态。
🐧虚函数表:
虚函数的实现通常依赖于一个被称为虚函数表(虚表)的数据结构。每个类都有一个虚表,其中包含该类的虚函数的地址。每个对象都包含了一个指向其类的虚表的指针,这个指针被称为虚指针。
当调用一个虚函数时,编译器会使用对象的虚指针查找虚表,并根据虚表中的函数地址来执行相应的虚函数。这就是可以根据对象类型来调用哪个函数的原因。
4. 虚函数和纯虚函数的区别
🐧虚函数:
-
有实现:虚函数有函数的声明和实现;
-
可选实现:派生类可以选择是否覆盖虚函数。如果派生类没有提供实现,则使用基类的默认实现。
-
允许实例化:虚函数的类可以被实例化。即你可以创建⼀个虚函数的类的对象。
-
调用靠对象类型决定:在运行时,根据对象的实际类型来决定调用哪个版本的虚函数。
-
使用virtual关键字声明:虚函数使⽤ virtual 关键字声明,但不包含 = 0 。
🐧纯虚函数:
5. 虚函数是的实现
当类包含虚函数时,编译器会为该类生成一个虚函数表(vtable)。
每个对象实例包含一个虚表指针(vptr),它指向对象所属类的虚函数表。
当通过基类指针或引用调用虚函数时,编译器会使用对象的虚表指针查找虚函数表中对应的虚函数实现,并进行调用。
虚函数的实现依赖于虚表。每个类都有一个虚表,里面有这个类的虚函数地址;每个对象都有指向它的类的虚表的指针,这个指针称为虚指针。
当调用虚函数时,编译器会调用对象的虚指针查找虚表,通过虚函数的地址来执行相应的虚函数。