C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分

一、多态的概念和定义

1.1 什么是多态?

多态就是去完成某个行为时,不同的对象就会产生出不同的状态。

例如:购买火车票时,普通人全票,学生半价买票。

1.2 多态的定义及实现

<1> 虚函数

在使用多态前引入一个概念——虚函数

  • 即被virtual修饰的类成员函数称为虚函数多态的构成条件
	//BuyTicket()被virtual关键字修饰,就被称为虚函数
	virtual void BuyTicket()
	{
     
		cout << "全价买票" << endl;
	}

<2>多态的构成条件和虚函数重写

要在继承中使用多态我们要牢牢把握两个条件

  1. 必须通过基类的指针或者引用调用虚函数
  2. 被调用的函数必须是虚函数,且派生类必须对虚函数进行重写

在上面的前提下我们还要记住重写的两个条件
3. 父类中的函数都是虚函数
4. 函数名、参数、返回值都要相同
下面通过一段代码掌握多态的定义和使用,其中重写又被称为覆盖

C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第1张图片
结果
C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第2张图片
注意:
子类重写虚函数时,可以不加virtual关键字,但这是一种不规范写法,不建议使用
C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第3张图片

<3> 虚函数重写的两个例外

  1. 协变(基类和派生类虚函数返回值类型不同)
    C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第4张图片
  2. 析构函数的重写(基类与派生类析构函数的名字不同)
    C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第5张图片
    上面这种情况如果子类在堆上有空间的申请而为调用子类析构函数,必然造成内存泄漏,因此父类最好都加virtual
    C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第6张图片

<4> C++11 final和override

从上面可以看出,C++对函数重写的要求比较严格,但是有些情况下由于疏忽,可能会导致函数名字母次序写反而无法构成重写,而这种错误在编译期间是不会报出的,只有在程序运行时没有得到预期结果才来debug会得不偿失,因此:C++11提供了override和final两个关键字,可以帮助用户检测是否重写。

  1. final:修饰虚函数,表示该虚函数不能再被继承。

C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第7张图片

  1. override:检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错
    C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第8张图片

二、抽象类

2.1 概念

在虚函数的后面写上 =0 ,则这个函数为纯虚函数包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承.
C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第9张图片

2.2 接口继承和实现继承

  • 普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现
  • 虚函数的继承是一种接口继承,派生类继承的是基类虚函数的接口,目的是为了重写,达成多态,继承的是接口。
  • 所以如果不实现多态,不要把函数定义成虚函数。

三、重载、重写和重定义的区分(重点)

C++多态——多态、抽象类的基本概念,重写、重载和重定义的区分_第10张图片

你可能感兴趣的:(C++从入门到入土,多态,抽象类,接口,虚函数)