【C++入门篇 - 8】:多态

多态


动态联编和静态联编

  • 静态联编:在编译时才知道执行哪段代码
    举例理解:今天我让几名同学来协助我完成一个项目,已经给各个同学分配好任务,这个分配任务的动作即为编译,”编译“后,各个同学就知道做什么了,这个就叫做静态联编
  • 动态联编:在运行时才知道执行哪段代码
    举例理解:今晚我告诉同学们,我将打电话给一名同学,但是还不知道打给哪位同学,直到打电话的时候才知道,这个就为动态编译

动态编译的条件

  1. 必须有类,且有继承关系;
  2. 通过基类指针或引用指向派生类对象或基类对象;
  3. 动态联编的行为是虚函数。

在以下的示例中均有体现。

多态

多态的概念

多态:同一个接口,可能会对应不同的函数。

前提条件

  1. 必须在继承中。派生类对象是基类对象。
  2. 通过基类的对象指针,可以指向基类对象,也可以指向派生类对象。
  3. 类中的函数必须是虚函数。

观察以下代码:
在这里插入图片描述
以上代码出现错误,解决的方法:引入虚函数

虚函数

虚函数,存在于类中,通过virtual关键字修饰的函数。

访问方式:通过对象访问 或 通过对象地址访问。
举例:

#include<iostream>

class A
{
public:
	virtual void fun() { printf("A\n"); } //虚函数
};

class B
{
public:
	void fun(){ printf("B\n"); }
};

typedef void(*pFun)(); //定义一个函数指针的类型
void main()
{
	A a;
	a.fun();  //第一种访问方式:通过对象访问
	pFun p; //表示一个指向void返回值,无参函数的指针

	p = (pFun)(*(int *)*(int *)&a); //只有虚函数才能用此操作
	p(); //第二种访问方式:通过对象地址访问
}

在这里插入图片描述

下面来说说继承中虚函数的原理
现在来观察以下代码:当更换pa指针的地址为b时,最终调用的fun还是A类中的fun函数。
在这里插入图片描述
当我们加上虚函数时,就不会出现这种情况了:
在这里插入图片描述
在这里插入图片描述

虚函数的特点

  1. 在类中定义了一个虚函数,系统会为这个类维护一个虚函数列表(函数指针数组)
  2. 基类中存在虚函数,派生类中的同名函数(返回值类型、函数名、参数列表都相同)自动成为虚函数,写不写关键字无所谓。
  3. 如果类中有多个虚函数,按声明顺序从上往下,把虚函数的首地址放入虚函数列表。
  4. 虚函数列表不会被继承,列表中的表项会被继承。
  5. 如果派生类中存在同名虚函数,会在里列表中替换掉继承过来的父类的虚函数。
    在这里插入图片描述
  6. 如果派生类中有虚函数且不和父类同名,会在列表的尾部添加该函数的首地址。

多态的实现

通过类的继承虚函数实现多态。
举例:

#include<iostream>

class A
{
public:
	virtual void fun() { printf("A::fun\n"); } 
	A(){ printf("A的构造\n"); }
	~A(){ printf("A的析构\n"); }
};

class B:public A
{
public:
	void fun(){ printf("B::fun\n"); }
	B(){ printf("B的构造\n"); }
	~B(){ printf("B的析构\n"); }
};

class C :public A
{
public:
	void fun(){ printf("C::fun\n"); }
	C(){ printf("C的构造\n"); }
	~C(){ printf("C的析构\n"); }
};

// void fun(boss基类指针)
//{
//	玩家.攻击(boss基类指针->对象)
//}

void main()
{
	A *pa = new B;
	pa->fun();
	delete pa;

	//pa = new C;
	//pa->fun();
	//delete pa;
}

在这里插入图片描述

解决bug的方法:类中有虚函数,析构函数必须是虚析构。
(构造、析构不会被继承,析构函数也会放到函数列表当中)
在这里插入图片描述

纯虚函数

纯虚函数,是虚函数,没有函数定义。

  • 有纯虚函数的类叫抽象基类,抽象基类是无法定义对象的。
    在这里插入图片描述
  • 抽象基类必须派生出子类,并重写纯虚函数。如果派生类没有重写虚函数,该派生类继承作为抽象基类存在。
  • 可以定义抽象基类为指针。

final

父类的虚函数或纯虚函数在子类中依然是虚函数。
有时我们并不希望父类的某个函数在子类中被重写。
在C++11 及以后可以用关键字final来避免该函数再次被重写。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

街 三 仔

你的鼓励是我创作的最大动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值