c++多态

目录

多态的概念

多态实现计算器案例

c++如何实现动态绑定

纯虚函数和抽象类

纯虚函数和多继承

虚析构函数

虚析构函数作用

纯虚析构函数

[重载 重定义 重写](#重载 重定义 重写)


多态的概念

多态:一种接口,多种形态

静态多态:如果函数的调用,在编译阶段就可以确定函数的调用地址,并产生代码,就是静态多态(编译时多态)

动态多态:调用地址不能编译不能在编译期间确定,而需要在运行时才能决定,这这就属于晚绑定(动态多态,运行时多态)

发生多态的四个条件:

父类中有虚函数

必须发生继承

子类必须重写虚函数(函数名 参数 返回值一致 函数的内容可以不一致)

父类的指针或引用指向子类的对象

cpp 复制代码
#include <iostream>

using namespace std;

class Animal
{
    public:
		virtual void speak()
		{
			cout << "动物在说话" << endl;
		}
};
class Dog:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "狗在说话" << endl;
		}
};
class Cat:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "猫在说话" << endl;
		}
};
//如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
void do_work(Animal &obj)//多态接口 一个函数实现不同功能
{
	obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
}

void test01()
{
	Animal p1;
	do_work(p1);//动物

	Dog p2;
	do_work(p2);//狗
	
	Cat p3;
	do_work(p3);//猫
}

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

多态实现计算器案例

cpp 复制代码
#include <iostream>
using namespace std;

class Calc
{
    public:
		virtual int mycalc(int a,int b)
		{
			return 0;		
		}
};
		
class Add:public Calc
{
    public:
		int mycalc(int a,int b)
		{
			return a + b;		
		}

};
class Mul:public Calc
{
    public:
		int mycalc(int a,int b)
		{
			return a * b;		
		}

};
class Sub:public Calc
{
    public:
		int mycalc(int a,int b)
		{
			return a - b;		
		}

};
		
int do_calc(int a,int b,Calc &obj)
{
	return obj.mycalc(a,b);
}

void test01()
{
	Add p1;
	cout << do_calc(3,4,p1) << endl;
	
	Mul p2;
	cout << do_calc(3,4,p2) << endl;

	Sub p3;
	cout << do_calc(3,4,p3) << endl;

}

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

c++如何实现动态绑定

为什么可以根据传入对象的不同来执行不同的语句?

纯虚函数和抽象类

纯虚函数:将虚函数等于0 实质是将虚函数 表的函数入口设为NULL

抽象类:一个类如果有纯虚函数,那么这个类就是一个抽象类,抽象类不能实例化对象

继承抽象类的子类也是一个抽象类,如果子类重写了虚函数,那么子类就不是抽象类

cpp 复制代码
class Calc
{
    public:
        virtual int mycalc(int a,int b) = 0;//虚函数等于0 纯虚函数
};

class Mob:public Calc
{
    public:
          //子类继承了抽象类 子类也是抽象类
           //如果子类重写虚函数 就不是抽象类
};

//如果有纯虚函数的类 叫做抽象类 抽象类无法实例化对象
void test()
{
    //Cacl p;//错误 
    Mod p1;
}

纯虚函数和多继承

多继承带来了一些争议,但是接口继承可以说一种毫无争议的运用了。
绝大数面向对象语言都不支持多继承,但是绝大数面向对象对象语言都支持接口的概念, c++ 中没有接口的概念, 但是可以通过纯虚函数实现接口。
接口类中只有函数原型定义,没有任何数据定义。
多重继承接口不会带来二义性和复杂性问题。接口类只是一个功能声明,并不是功能实现,子类需要根据功能说 明定义功能实现。
注意 : 除了析构函数外,其他声明都是纯虚函数。

虚析构函数

虚析构函数作用

在调用基类的析构函数之前,先调用子类的析构函数

cpp 复制代码
#include <iostream>

using namespace std;

class Animal
{
    public:
		virtual void speak()
		{
			cout << "动物在说话" << endl;
		}
		virtual ~Animal()
		{
			cout << "动物的析构" << endl;
		}
};
class Dog:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "狗在说话" << endl;
		}
		~Dog()
		{
			cout << "狗的析构" << endl;
		} 
};
class Cat:virtual public Animal
{
    public:
		//重写虚函数 函数的返回值 参数 函数名一样
		void speak()
		{
			cout << "猫在说话" << endl;
		}
};
//如果两个类发生了继承 父类和子类编译器都会自动转换 不需要人为转换
void do_work(Animal &obj)//多态接口 一个函数实现不同功能
{
	obj.speak();//地址早绑定->加上函数前面加上virtual 地址晚绑定
}

void test01()
{
	Animal *p = new Dog;
	p->speak();//调用狗的speak
	delete p;//加virtual 调用动物的析构 加virtual之后先调用狗的析构 再调用动物的析构
}

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

纯虚析构函数

虚构函数等于零

class Animal

{

public:

virtual void speak()

{

cout << "动物在说话" << endl;

}

virtual ~Animal() = 0;//

};

重载 重定义 重写

重载:

函数名相同

同一个作用域

参数的个数、顺序、类型不一致

const也可以成为重载的条件

重定义:

发生继承

子类和父类有同名的变量和函数,父类中同名的变量和函数会被隐藏

重写:

父类中有虚函数

发生了继承

子类重写了虚函数

函数名、返回值、参数一致,函数体不一致

相关推荐
神仙别闹15 分钟前
基于C#+Mysql实现(界面)企业的设备管理系统
开发语言·mysql·c#
大柏怎么被偷了22 分钟前
【C++算法】位运算
开发语言·c++·算法
程序猿方梓燚24 分钟前
C/C++实现植物大战僵尸(PVZ)(打地鼠版)
c语言·开发语言·c++·算法·游戏
CPP_ZhouXuyang24 分钟前
C语言——模拟实现strcpy
c语言·开发语言·数据结构·算法·程序员创富
闻缺陷则喜何志丹25 分钟前
【C++前后缀分解 动态规划】2100. 适合野炊的日子|1702
c++·算法·动态规划·力扣·前后缀分解·日子·适合
Zucker n30 分钟前
猫狗识别大模型——基于python语言
开发语言·python
bluebonnet271 小时前
【Rust练习】15.match 和 if let
开发语言·后端·rust
yueqingll1 小时前
020、二级Java选择题综合知识点(持续更新版)
java·开发语言
冲,干,闯1 小时前
VScode相关问题与解决
c++·ide·vscode
计算机学姐1 小时前
基于python+django+vue的在线学习资源推送系统
开发语言·vue.js·python·学习·django·pip·web3.py