C++多态(全)

多态

概念

调用函数的多种形态,

多态构成条件

1)父子类完成虚函数的重写(三同:函数名,参数,返回值相同)

2)父类的指针或者引用调用虚函数

虚函数

被virtual修饰的类成员函数

注意

1)只有类的非静态成员函数前才可以加上virtual 

2)虚函数的virtual与虚继承的virtual是同一个关键字。虚函数中的virtual是为了实现多态,虚继承的virtual是为了菱形继承中数据冗余和二义性。

虚函数的重写

也叫虚函数的覆盖

派生类中有一个完全相同的虚函数(返回值类型相同,函数名相同,参数列表相同),就叫做派生类的虚函数重写了基类的虚函数

结果:通过父类Person的指针或引用调用虚函数

父类指针要是指向父类对象则调用父类的虚函数

要是指向子类对象则调用子类虚函数

#include<iostream>
using namespace std;
class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票半价" << endl;
	}
};
class Student :public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "买票半价" << endl;
	}
};
void Func(Person& people)
{
	people.BuyTicket();
}
int main()
{
	Student s;

	Func(s);
	return 0;
}
注意

1)派生类的虚函数可以不用加上virtual关键字(不规范,建议加上)

虚函数的两个例外

1)协变

基类和派生类的返回值不同

当基类虚函数返回基类对象的指针或引用

派生类虚函数返回派生类对象的指针或引用

#include<iostream>
using namespace std;

//基类
class A
{};
//子类
class B : public A
{};
//基类
class Person
{
public:
	//返回基类A的指针
	virtual A* fun()
	{
		cout << "A* Person::f()" << endl;
		return new A;
	}
};
//子类
class Student : public Person
{
public:
	//返回子类B的指针
	virtual B* fun()
	{
		cout << "B* Student::f()" << endl;
		return new B;
	}
};
void Func(Person& p)
{
	p.fun();
}
int main()
{
	Student s;

	Func(s);
	return 0;
}

2)析构函数的重写

基类和派生类的析构函数名字不同

当基类的析构函数是虚函数,只要派生类析构函数定义,就构成重写

作用:

要是没有重写,指向子类的指针只会调用父类的析构函数,有可能造成内存泄漏

推荐:

一般把父类的析构函数写成虚函数,反之发生内存泄漏

注意:

在继承中,子类和父类的析构函数会构成隐藏就是因为,虽然子类析构函数和父类的析构函数函数名虽然不同,但是为了构成重写,编译后的析构函数名字会统一处理为destructor();

void test2()
{
	Person* p1 = new Person;
	Person* p2 = new Student;
	delete p1;
	delete p2;
	//本来希望指向父类的指针析构父类
	//指向子类的指针去析构子类
	//因此需要虚函数,构成重写
}

c++11

1)override:检查派生类虚函数是否重写了基类的某个虚函数,没有则编译错误

//子类
class Student : public Person
{
public:
	//子类完成了父类虚函数的重写,编译通过
	virtual void BuyTicket() override
	{
		cout << "买票-半价" << endl;
	}
};

2)final:修饰虚函数,表示该虚函数不能再重写

//父类
class Person
{
public:
	//被final修饰,该虚函数不能再被重写
	virtual void BuyTicket() final
	{
		cout << "买票-全价" << endl;
	}
};

易错例题

纯虚函数

在虚函数后面写上=0

抽象类(接口类):包含纯虚函数的类

特点

1)抽象类不能实例化对象

2)强制派生类重写虚函数(不重写则会继承纯虚函数,又变为抽象类了又不能实例化对象了)

3)用抽象类(父类)的指针调用虚函数

作用

1)抽象类能更好的

#include <iostream>
using namespace std;
//抽象类(接口类)
class Car
{
public:
	//纯虚函数
	virtual void Drive() = 0;
};
int main()
{
	Car c; //抽象类不能实例化出对象,error
	return 0;
}

#include <iostream>
using namespace std;
//抽象类(接口类)
class Car
{
public:
	//纯虚函数
	virtual void Drive() = 0;
};
//派生类
class Benz : public Car
{
public:
	//重写纯虚函数
	virtual void Drive()
	{
		cout << "Benz-舒适" << endl;
	}
};
//派生类
class BMV : public Car
{
public:
	//重写纯虚函数
	virtual void Drive()
	{
		cout << "BMV-操控" << endl;
	}
};
int main()
{
	//派生类重写了纯虚函数,可以实例化出对象
	Benz b1;
	BMV b2;
	//不同对象用基类指针调用Drive函数,完成不同的行为
	Car* p1 = &b1;
	Car* p2 = &b2;
	p1->Drive();  //Benz-舒适
	p2->Drive();  //BMV-操控
	return 0;
}

抽象类作用

1)用来表达没有实例对象的抽象类型

2)强制子类重写虚函数(同override)

原理

多态调用:运行时,到指向对象的虚表中找虚函数调用

普通调用:编译时,调用的对象是那个类型就调用它的函数

虚表:虚函数表,存虚函数的地址,目标实现多态

虚基表:存的是当前位置距离虚基类部分的偏移量,解决菱形继承和二义性的问题

虚函数和普通函数一样:在代码段中,不是在虚表中的(虚表内的是虚函数的地址

虚表在常量区

相关推荐

  1. <span style='color:red;'>C</span>++<span style='color:red;'>多</span><span style='color:red;'>态</span>

    C++

    2024-05-01 12:42:03      48 阅读
  2. 八股文 c++

    2024-05-01 12:42:03       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-01 12:42:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-01 12:42:03       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-01 12:42:03       82 阅读
  4. Python语言-面向对象

    2024-05-01 12:42:03       91 阅读

热门阅读

  1. redis运维篇下篇

    2024-05-01 12:42:03       29 阅读
  2. Qt5配置Opencv读取一张图像

    2024-05-01 12:42:03       35 阅读
  3. 2024年第二十一届五一数学建模竞赛A题思路

    2024-05-01 12:42:03       30 阅读
  4. CSS中的Float(浮动):深入解析与运用技巧

    2024-05-01 12:42:03       31 阅读
  5. vue钩子函数、生命周期

    2024-05-01 12:42:03       32 阅读
  6. 美易官方:亚马逊第一季度营收1433.13亿美元

    2024-05-01 12:42:03       33 阅读
  7. Fastadmin 日常项目常见用法整理

    2024-05-01 12:42:03       34 阅读
  8. 深入解析Jackson的ObjectMapper:核心功能与方法指南

    2024-05-01 12:42:03       38 阅读
  9. W801学习笔记十六:掌机系统——启动第一个应用

    2024-05-01 12:42:03       39 阅读
  10. 论文辅助笔记:TEMPO 之 utils.py

    2024-05-01 12:42:03       28 阅读
  11. list模拟实现

    2024-05-01 12:42:03       24 阅读