【C/C++】详解C++三大特性之一:多态

本文详细探讨C++的多态特性,包括多态的概念、虚函数的重写规则、抽象类的定义,以及多态的实现原理。通过实例解析虚函数表的构建过程,阐述动态绑定和多继承下的对象模型。
摘要由CSDN通过智能技术生成

一、多态的概念和定义

前提: 这篇文章是在 vs2019下的 x86 程序中,涉及的指针都是4字节,如果在其他平台下,可能需要考虑指针8字节的问题等等。

1.1 多态的概念

  1. 完成某个行为时,不同的对象会产生不同的状态。比如买票,小孩有半价票,成人有成人票,退伍军人会免票,这就是多态的一个实际例子
  2. 多态是对继承进行扩展,即拥有了基类的一部分内容,又想在某些继承函数中添加独立的处理方式

在这里插入图片描述

1.2 多态的构成条件

前提:必须在继承的体系下

  1. 实现:基类函数必须是虚函数,子类必须对该虚函数进行"重写"
  2. 调用:通过基类对象的指针或者引用来调用虚函数

虚函数: 被virtual关键字修饰的类成员函数称为虚函数

多态的体现:

  1. 只有程序运行时才能体现出多态的性质,根据指针或者引用指向不同类的对象,从而调用对应的虚函数
  2. 编译阶段只进行语法检测,编译器并不知道指针指向哪一个类对象

二、虚函数的重写

2.1 重写规则

  1. 一定是派生类对基类的虚函数进行重写,如果基类中的不是虚函数则不能够成重写
  2. 派生类对虚函数重写,必须保证函数原型和基类中的一致,即:返回值,函数名,参数列表都要一样 (特例:析构函数和协变)
class A
{
   
public:
	virtual void buy()
	{
   
		cout << "基类" << endl;
	}
};
class B : public  A
{
   
public:
	virtual void buy()
	{
   
		cout << "派生类" << endl;
	}
};

注意:派生类重写基类虚函数时,派生类不加 virtual 关键字也可以构成重写,因为基类中的虚函数被继承下来任然保持虚函数属性,但这样写不符合规范

2.1 特殊的重写

协变:
派生类对基类的虚函数进行重写时,与基类的返回值不同,基类虚函数返回基类对象的指针或者引用,而派生类虚函数返回派生对象的指针或者引用,称为协变。

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;}
};

析构函数:
只要基类对析构函数用virtual修饰,则派生类中的析构函数就形成了重写,虽然函数名不同,再编译器对析构函数的名称进行了特殊处理,编译之后析构函数名称同一处理为destructor

class A
{
   
public:
	virtual ~A()
	{
   
		cout << "基类析构" << endl;
	}
};
class B : public  A
{
   
public:
	~B()
	{
   
		cout << "派生类析构" << endl;
	}
};
void Test()
{
   
	A* a = new A;
	A* b = new B;
	delete a;
	delete b;
}

注意事项:

  1. 如果派生类涉及内存管理,则基类中的析构函数必须用virtual修饰,否则可能造成内存泄漏。原因:基类指向动态开辟的派生类地址,delete 时如果基类中的析构不是虚函数(没有构成重写),派生类的资源将得不到释放
  2. 编译器会先调用派生类的析构函数,再调用基类的析构函数
  3. 重写之后,派生类虚函数和基类虚函数访问权限可以不同&#x
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值