当前位置: 首页 > news >正文

C++多态知识点梳理

多态

多态的概念:

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

比如构成多态的俩个父子类,我们调用同一个函数,可能会产生不同的行为,比如普通人买票全价,学生买票半价或者打八折。

class Person
{
public:
	virtual void BuyTicke() 
	{ 
		cout << "买票-全价" << endl;
	}
};
class Student:public Person
{
public:
	virtual void BuyTicke()
	{
		cout << "买票-半价" << endl;

	}
};
void Func(Person& p)
{
	p.BuyTicke();
}
void Func(Person* p)
{
	p->BuyTicke();
}

int main()
{
	Person p;
	Person* ps = &p;
	Func(ps);
	Student s;
	Func(&s);
	return 0;
}

我们可以发现这个代码的神奇之处,按照我们之前的理解,这个代码p.BuyTicke();/p->BuyTicke();都是按照类型调用的。会调用Person类的函数。
在这里插入图片描述
这个就是多态的魅力,通过传入对象的不同,可以实现不同的行为。

.

多态的定义及实现

多态的构成条件

首先构成多态的要满足俩种条件:
1 被调用的函数必须是虚函数,且必须派生类的虚函数进行重写
2 必须是父类的指针或者引用;

什么是虚函数呢?
就是在普通的成员函数前面加上virtual关键字,就会变成虚函数(注意一定是成员函数)。普通函数是不行的。
虚函数的重写:虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

虚函数重写的俩个例外:

  1. 派生类被调用的虚函数可以不加virtual

class Person
{
public:
virtual void BuyTicke()
{
cout << “买票-全价” << endl;
}
};
class Student:public Person
{
public:
void BuyTicke()
{
cout << “买票-半价” << endl;

}

};

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

class Person
{
public:
	virtual Person& BuyTicke()
	{
		cout << "买票-全价" << endl;
		return *this;
	}
	
};
class Student :public Person
{
public:
	 Student& BuyTicke()
	{
		cout << "买票-半价" << endl;
		return *this;
	}
};

int main()
{

	return 0;
}

面试常考题

析构函数是虚函数吗?为什么呢?

首先析构函数前面加上virtual关键字满足三同,因为它的名字被编译器给默认生成destory(),因此析构函数是虚函数。为什么它要变成虚函数呢?

class Person
{
public:
	~Person()
	{
		cout << "~Person()" << endl;
	}
};

class Student:public Person
{
public:
	~Student()
	{
		cout << "~Student()" << endl;
	}
};
int main()
{
	Person p;
	Student st;
	return 0;
}

这边我们看不构成虚函数也是没问题的。

在这里插入图片描述

但是我们改一下代码,然后再看一下这种情况。

class Person
{
public:
	~Person()
	{
		cout << "~Person()" << endl;
	}
};

class Student:public Person
{
public:
	~Student()
	{
		cout << "~Student()" << endl;
		delete st;
	}

	string* st = new string;
	
};

int main()
{
	Person* p = new Student;
	delete p;
	return 0;
}

在这里插入图片描述
这边就发生了内存泄漏的问题,原因是因为这个delete p;只调用了p->destory()+operator delete()释放空间,这个p是Person类型,普通对象调用看对象的类型,但是如何解决这个问题呢?让他变成多态不就行了吗?让他看指向的对象就调用哪个对象的析构函数。

class Person
{
public:
	virtual ~Person()
	{
		cout << "~Person()" << endl;
	}
};

class Student:public Person
{
public:
	virtual~Student()
	{
		cout << "~Student()" << endl;
		delete st;
	}

	string* st = new string;
	
};

int main()
{
	Person* p = new Student;
	delete p;
	return 0;
}

在这里插入图片描述

final 和override关键字

final让派生类不能重写虚函数;

class A
{
public:
	virtual void Func()final
	{}
};
class B:public A
{
public:
	virtual void Func()
	{}
};

int main()
{
	return 0;
}

override检查派生类的虚函数是否构成重写

class A
{
public:
	virtual void Func()
	{}
};
class B:public A
{
public:
	virtual void Func()override
	{}
};

int main()
{
	return 0;
}

5 重载、覆盖(重写)、隐藏(重定义)的对比

重载:在一个作用域 函数名相同,参数类型不同;
覆盖(重写):虚函数+三同;
隐藏:基类和派生类中只要命名相同就会构成隐藏;

在这里插入图片描述

相关文章:

  • Java笔记5——面向对象(下)
  • 如何在Windows 10系统中查看已连接WiFi密码-亲测可用-优雅草卓伊凡
  • 使WebSocket 稳定可靠,需要考虑的方向
  • 2025年十六届蓝桥杯Python B组原题及代码解析
  • 今日行情明日机会——20250414
  • css实现一键换肤
  • 入门-C编程基础部分:1、环境搭建
  • MySQL 超详细安装教程与常见问题解决方案
  • 优先级队列(堆二叉树)底层的实现:
  • 十四、C++速通秘籍—函数式编程
  • JAVA EE_文件操作和IO
  • 蓝桥杯 web 常考到的一些知识点
  • OpenCV 图形API(33)图像滤波-----高斯模糊函数gaussianBlur()
  • 3D版的VLA:从3D VLA、SpatialVLA到PointVLA——3D点云版的DexVLA,在动作专家中加入3D数据
  • 人工智能100问☞第4问:人工智能与机器学习、深度学习的区别?
  • Matplotlib库详解
  • 网页防篡改与盗链防护:实时监控与自动化修复实践
  • python中,sort(reverse=True)与列表.reverse的区别
  • 【集成电路版图设计学习笔记】2. 基本绘制的layer层和电路失效机制
  • ubuntu22.04安装zabbix7.0
  • 硅料收储挺价“小作文”发酵光伏板块罕见大涨,知情人士:确实在谈
  • 市场监管总局等五部门约谈外卖平台企业
  • 习近平同巴西总统卢拉会谈
  • 多地警务新媒体整合:关停交警等系统账号,统一信息发布渠道
  • 《新时代的中国国家安全》白皮书(全文)
  • 有关部门负责人就《新时代的中国国家安全》白皮书答记者问