C++——多态
目录
多态
什么是多态
多态的两种形式
静态的多态(编译时多态)
动态的多态(运行时多态)
实现条件:
虚函数
虚函数重写
重载、覆盖(重写)、隐藏(重定义)的对比
纯虚函数(抽象类)
多态的原理
多态常考题目
多态
什么是多态
概念:多态简单来说就是指多种形态,具体点就是不同的对象做一件事会产生不同的结果,更加专业一点的说是指:同一操作作用于不同对象时,会产生不同的执行结果。简单来说,就是 "同一个接口,不同实现"。
多态的两种形式
静态的多态(编译时多态)
编译时多态在编译阶段就确定调用哪个函数,主要通过函数重载和模板实现。
(1)函数重载(Function Overloading)
在同一作用域内,允许定义多个同名函数,但它们的参数列表(参数类型、数量、顺序)必须不同。编译器会根据实参类型在编译时匹配对应的函数。
(2)模板(Templates)
通过模板可以实现通用代码,编译器会根据传入的具体类型在编译时生成对应版本的函数或类,这也是一种静态多态。
动态的多态(运行时多态)
运行时多态在程序运行时才确定调用哪个函数,是 C++ 中更核心的多态形式,通过虚函数(Virtual Function) 和继承实现。
实现条件:
- 存在继承关系(子类继承父类);
- 父类中声明虚函数(使用
virtual
关键字); - 子类重写(Override)父类的虚函数;
- 通过父类指针或引用指向子类对象,调用虚函数。
例如:
class Animal
{
public:virtual void eat(){cout << "Animal eat" << endl;}};class Dog :public Animal
{
public:void eat(){cout << "dog eat" << endl;}};class Cat :public Animal
{
public:void eat(){cout << "Cat eat" << endl;}
};void Func(Animal& who)
{who.eat();
}int main()
{Animal a;Animal & a1= a;a1.eat();Func(a);cout << endl;Dog d;Dog& d1 = d;d1.eat();Func(d);cout << endl;Cat c;Cat& c1 = c;c1.eat();Func(c);return 0;
}
虚函数
虚函数概念:即被virtual修饰的类成员函数称为虚函数
虚函数重写
在Dog和Cat中的eat函数都是Animal函数中eat函数的重写
class Animal
{
public:virtual void eat(){cout << "Animal eat" << endl;}};class Dog :public Animal
{
public:void eat(){cout << "dog eat" << endl;}};class Cat :public Animal
{
public:void eat(){cout << "Cat eat" << endl;}
};
虚函数重写的两个例外:
class A{};
class B : public A {};
class Person {
public:virtual A* f() {return new A;}
};
class Student : public Person {
public:virtual B* f() {return new B;}
};
class Animal
{
public:virtual void eat(){cout << "Animal eat" << endl;}};class Dog :public Animal
{
public:void eat(){cout << "dog eat" << endl;}~Dog(){delete p1;cout << "~Dog" << endl;}
private:int* p1 = new int(10);};
int main()
{Animal* p1 = new Dog;delete p1;
}
如果重写的编译时会报错
class Car
{
public:virtual void Drive() final {}
};
class Benz :public Car
{
public:virtual void Drive() {cout << "Benz-舒适" << endl;}
};
重载、覆盖(重写)、隐藏(重定义)的对比
重载的概念:在同一作用域内,声明多个函数名相同、参数列表不同的函数(与返回值无关)
覆盖的概念:在继承关系中,子类重新实现父类中已声明为虚函数的函数,且函数签名完全一致
隐藏的概念:在继承关系中,子类声明了与父类同名但不满足重写条件的函数,导致父类函数“隐藏”
纯虚函数(抽象类)
多态的原理
多态是依靠虚函数来实现,将一个类的一个成员函数写成虚函数,那么这个类对象就会自动生成一个虚表指针,虚表指针指向虚表,用于存放虚函数,一个派生类如果继承了一个含有虚函数的基类,那么这个派生类对象也会产生一个虚表指针,虚表指针指向虚表,如果派生类中重写了虚函数,那么我们可以认为,他将原来基类的虚表中的虚函数地址换成了派生类中重写的虚函数地址,在一个函数中调用时,我们就可以通过对象中的虚表来具体调用那个函数。
如果一个基类中有虚函数也有普通成员函数,那么普通成员函数是不会放在虚表中的,而是放在代码段中。
多继承派生类的未重写的虚函数放在第一个继承基类部分的虚函数表中
多态常考题目
1. 什么是多态?
3. 多态的实现原理?