十七. C++多态详解

本文详细介绍了C++中的多态特性,包括静态多态与动态多态的区别、多态的实现机制、动态绑定、虚函数的作用,以及虚析构函数的应用。通过实例展示了如何利用多态进行程序设计,并探讨了抽象基类与纯虚函数的概念。
摘要由CSDN通过智能技术生成

目录

多态

无多态问题:早绑定

动态绑定

动态捆绑机制原理

多态案例:计算器

抽象基类与纯虚函数

虚析构与纯虚析构


多态

C++支持编译时多态(静态多态)和运动时多态(动态多态),运算符重载和函数重载就是编译时多态,而派生类和虚函数实现运动时多态。

静态多态和动态多态的区别在于函数地址是早绑定(静态联编)还是晚绑定(动态联编)。如果函数的调用,在编译阶段可以确定函数的调用地址并产生代码,就是静态多态,就是说地址是早绑定的。而如果函数的调用,其地址不能编译不能在编译期间确定,而需要在运行时才能确定,这就是属于晚绑定(动态联邦、运行时多态)。

多态成立条件:

  • 继承
  • 子类重写父类虚函数(与父类完全一致,子类这种virtual关键字可写可不写,建议写)

无多态问题:早绑定

代码示例如下:其结果为:动物在说话!但是我们给doSpeak传入的对象为cat,而不是animal对象,输出结果应该为小猫在说话。

#define _CRI_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;

class Animal
{
public:
	void speak()
	{
		cout << "动物在说话" << endl;
	}
};

class Cat :public Animal
{
public:
	void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
//调用doSpeak, speak函数的地址早就绑定好了,早绑定(编译阶段就已确定好了地址),叫静态联编
//如果想调用猫的speak,不能提前绑定好函数的地址,所以需要在运行时去确认函数地址
//动态联编, 写法doSpeak 方法改为虚函数,在父类上申明一个虚函数, 发生了多态
//多态:父类的引用或指针 指向子类对象
void doSpeak(Animal& animal)      //Animal& animal =cat
{
	animal.speak();
}
//如果发生了继承的关系,编译器允许进行类型转换
void test01()
{
	Cat cat;
	doSpeak(cat);
}

int main()
{
	test01();
	return 0;
}

当绑定在程序运行之前(由编译器和连接器)完成时,称为早绑定(静态联编)。因为编译器在只有Animal地址时并不知道要调用的正确函数。编译是根据指向对象的指针或引用的类型来选择函数调用。这个时候由于DoBussiness的参数类型是Animal&,编译器确定了应该调用的speak是Animal::speak的,而不是真正传入的对象cat::speak。

动态绑定

解决此现象的方法为动态绑定(动态联编),实现动态联编的方法为虚函数(virtual function)。C++动态多态性是通过虚函数实现的,虚函数允许子类(派生类)重新定义父类(基类)成员函数,这种方法称为覆盖(重写)。

实现方法为在基类声明此函数时使用virtual关键字。

  • 为创建一个需要动态绑定的虚成员函数,可以简单在这个函数声明前面加上virtual关键字。
  • 如果一个函数在基类中被声明为virtual,那么在所有派生类中它都是virtual的。
  • 在派生类中virtua
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值