C++中的多态性

定义:

子类重新定义父类中有相同名称,返回值和参数的虚函数,主要在继承关系中出现。

基本条件:

重写的函数和被重写的函数必须都为virtual函数,并分别位于基类和派生类中,如果父类被重写的函数加了

vritual,子类继承父类,那么子类重写的函数加不加vritual都是虚函数

重写的函数和被重写的函数,返回值,函数名和函数参数必须完全一致;

cpp 复制代码
#include<iostream>
    using namespace std;
    class father
    {
    public:
    	virtual void fun()
    	{
    		cout << "father" << endl;
    	}
    };
    class child:public father
    {
    public:
    	virtual void fun()
    	{
    		cout << "child" << endl;
    	}
    };

函数隐藏

定义:在子类中只要和父类函数名字相同不是重写,一定是函数隐藏。

cpp 复制代码
class Base
    {
    	public:
    	void funA(){cout<<"funA()"<<endl;} 
    	virtual void funB(){cout<<"funB()"<<endl;} 
    };
    class Heri:public Base
    {
    	public:
    	void funA(){cout<<"funA():Heri"<<endl;} //函数隐藏因为不是虚函数
    	void funA(int a){cout<<"funA(int a):heri"<<a<<endl;} //函数隐藏参数不同
    	void funB(){cout<<"funB():heri"<<endl;} //函数重写
    };

多态的基本概念

静态多态: 函数重载 和 运算符重载属于静态多态,复用函数名

动态多态: 派生类和虚函数实现运行时多态

静态多态和动态多态区别:

静态多态的函数地址早绑定 - 编译阶段确定函数地址

动态多态的函数地址晚绑定 - 运行阶段确定函数地址

多态的基础: 需要有重写,子类重写父类的 返回值 名字 参数相同的虚函数,(只要父类的函数是虚函数即可)。

动态多态: 父类的指针或引用指向子类对象,并且通过该指针或引用调用子类重写的虚函数

多态的使用条件: 父类的指针或引用指向子类对象

cpp 复制代码
#include<iostream>
    #include<string>
    #include<vector>
    using namespace std;
    class Animal
    {
    public:
    	virtual void speak()
    	{
    		cout << "animal speak" << endl;
    	}
    	void work()
    	{
    		cout << "animal work" << endl;
    	}
    };
    class cat :public Animal
    {
    public:
    	void speak()
    	{
    		cout << "cat speak" << endl;
    	}
    	void work()
    	{
    		cout << "cat work" << endl;
    	}
    };
    class dog :public Animal
    {
    public:
    	void speak()
    	{
    		cout << "dog speak" << endl;
    	}
    	void work()
    	{
    		cout << "dog work" << endl;
    	}
    };
    int main() {
    	
    	Animal *a = new dog;
    	//speak 是函数重写 ,work是函数隐藏
    	a->speak();//调用的是dog里的speak函数
    	a->work();//调用的函数是隐藏函数时,调用函数的指针或对象是什么类型调用哪里的函数,调用的是animal里的work函数
    	return 0;
    }

C++中如何实现多态:

类的虚函数表

每个包含了虚函数的类都包含一个虚函数表(存放虚函数指针的数组,就是存放的是虚函数的地址),调用虚函

数,必须通过虚函数表找到虚函数的地址

当一个类(B)继承另一个类(A)时,类 B 会继承类 A 的函数的调用权。所以如果一个基类包含了虚函数,那么

其继承类也可调用这些虚函数,换句话说,一个类继承了包含虚函数的基类,那么这个类也拥有自己的虚函数表。

虚函数表在编译阶段被初始化

cpp 复制代码
class A {
    public:
    	virtual void vfunc1();
    	virtual void vfunc2();
    	void func1();
    	void func2();
    private:
    	int m_data1, m_data2;
    };
    class B : public A{//此时类B也拥有自己的虚表
    };

虚表指针

只要类中有虚函数,那么类中就会多一个成员变量,这个成员变量就是虚函数表的指针,调用虚函数,先访问这个对象里的虚函数表指针,通过虚函数表指针找到虚函数那个数组,在遍历数组找到虚函数地址

cpp 复制代码
class A {
    public:
        virtual void vfunc1();
        virtual void vfunc2();
        void func1();
        void func2();
    private:
        int m_data1, m_data2;
    };
    
    class B : public A {
    public:
        virtual void vfunc1();
        void func1();
    private:
        int m_data3;
    };
    
    class C: public B {
    public:
        virtual void vfunc2();
        void func2();
    private:
        int m_data1, m_data4;
    };
    
    int main() 
    {
        B bObject;
        A *p = & bObject;
        p->vfunc1();//父类指针调用虚函数,先通过父类指针访问对象bObject,找到对象里的虚表指针,这个虚表指针指向的虚表是类B的虚表,就上类B的虚表中找vfun1,类B重写了vfun1,所以调用的是子类的vfun1
    }

多态的好处:

1.更好的代码重用性:多态允许你使用父类指针或引用来操作子类对象,这意味着你可以编写通用的代码来处理不同类型的对象,从而提高代码的重用性。

2.代码的可扩展性:多态使得代码更加灵活和可扩展。当你需要添加新的子类时,不需要修改现有的代码,只需要在新子类中实现相应的方法即可。

3.更好的灵活性:多态使得你能够根据具体情况选择不同的实现方式,而不需要拘泥于固定的实现。这在处理复杂问题时非常有用。

相关推荐
chuxinweihui12 分钟前
数据结构——二叉树,堆
c语言·开发语言·数据结构·学习·算法·链表
陈大大陈29 分钟前
基于 C++ 的用户认证系统开发:从注册登录到Redis 缓存优化
java·linux·开发语言·数据结构·c++·算法·缓存
纪元A梦32 分钟前
华为OD机试真题——通过软盘拷贝文件(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题
看到我,请让我去学习38 分钟前
C语言基础(day0424)
c语言·开发语言·数据结构
studyer_domi41 分钟前
Matlab 复合模糊PID
开发语言·matlab
猫猫头有亿点炸1 小时前
C语言斐波拉契数列2.0
c语言·开发语言·算法
刚入坑的新人编程1 小时前
C++多态
开发语言·c++
西柚小萌新1 小时前
【Python爬虫实战篇】--Selenium爬取Mysteel数据
开发语言·爬虫·python
努力写代码的熊大1 小时前
c语言中文件操作详解
c语言·开发语言
QUST-Learn3D1 小时前
高精度并行2D圆弧拟合(C++)
开发语言·c++