面向对象--多态

多态分为两类:

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

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

静态和动态的区别:

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

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

#include<iostream>
using namespace std;
//2、定义一图形CShape类,其中有成员数据:宽度width和高度height,带构造函数。并建立两个派生类
//:矩形类和等腰三角形类。派生类中都包含一函数Area,分别用来计算矩形和等腰三角形的面积。
class Animal
{public://不要忘掉public
	//前面加上virtual关键字变为虚函数,编译器在编译的时候就不能确定函数调用
	virtual void speak()
	{
		cout << "动物在说话" << endl;
	}
};
class cat :public Animal
{
public:
	void speak()
	{
		cout << "小猫在说话" << endl;
	}
};
class dog :public Animal
{
public:
	void speak()
	{
		cout << "小狗在说话" << endl;
	}
};
//我们希望传入什么对象就调用什么对象,动态联编
void dospeak(Animal & animal)
{
	animal.speak();
}
//动态多态满足的条件:
//1,有继承关系
//2,子类重写父类中的虚函数
//多态使用:
//父类指针或引用指向子类对象
void test()
{
	cat c;
	dospeak(c);
	dog d;
	dospeak(d);
}
int main()
{
	test();
	return 0;
}

二,多态原理剖析

三,多态案列-计算机类

普通实现:

#include<iostream>
using namespace std;
class Calculator {
public:
	int getresult(string oper)
	{
		if (oper == "+")
		{
			return m_Num1 + m_Num2;
		}
		if (oper == "-")
		{
			return m_Num1 - m_Num2;
		}
		if (oper == "*")
		{
			return m_Num1 * m_Num2;
		}
	}
public:
	int m_Num1;
	int m_Num2;
};
void test()
{
	Calculator c;
	c.m_Num1 = 10;
	c.m_Num2 = 10;
	cout << c.m_Num1 << "+" << c.m_Num2 << "=" << c.getresult("+") << endl;
	cout << c.m_Num1 << "-" << c.m_Num2 << "=" << c.getresult("-") << endl;
	cout << c.m_Num1 << "*" << c.m_Num2 << "=" << c.getresult("*") << endl;
}
int main()
{
	test();
	return 0;
}

多态实现:

#include<iostream>
using namespace std;
class Calculator {
public:
	virtual int getresult()
	{
		return 0;
	}
	int m_Num1;
	int m_Num2;
};
class addcalculator :public Calculator//派生类注意语法
{
public:
	int getresult()
	{
		return m_Num1 + m_Num2;
	}
};
class descalculator :public Calculator {
public:
	int getresult()
	{
		return m_Num1 - m_Num2;
	}
};
class mulcalculator :public Calculator {
public:
	int getresult()
	{
		return m_Num1 * m_Num2;
	}
};
int main()
{
	Calculator* abc = new addcalculator;//父类指向子类
	abc->m_Num1 = 10;
	abc->m_Num2 = 10;
	cout << abc->m_Num1 << "+" << abc->m_Num2 << "="<<abc->getresult() << endl;
	delete abc;//堆区手动开辟手动释放,用完即销毁
	abc = new descalculator;//注意不要重定义
	abc->m_Num1 = 10;
	abc->m_Num2 = 10;
	cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getresult() << endl;
	delete abc;//堆区手动开辟手动释放,用完即销毁
abc = new mulcalculator;//父类指向子类
	abc->m_Num1 = 10;
	abc->m_Num2 = 10;
	cout << abc->m_Num1 << "*" << abc->m_Num2 << "=" << abc->getresult() << endl;
	delete abc;//堆区手动开辟手动释放,用完即销毁
	return 0;
}

多态优点:

1,代码组织结构清晰

2,可读性强

3,利用前期和后期的扩展以及维

四,纯虚函数和抽象类 

纯虚函数语法:

virtual 返回值类型 函数名 (参数列表)=0;

当类中有了纯虚函数,这个类也成为抽象类

抽象类特点:

1,无法实例化对象

2,子类必须重写抽象类中的纯虚函数,否则也属于抽象类

#include<iostream>
using namespace std;
class Base
{
public:
	virtual void func() = 0;
};
class Son:public Base
{
public:
	virtual void func()//必须重写父类中的纯虚函数
	{
		cout << "func调用" << endl;
	}
};
void test()
{
	Base* base = NULL;
	//base=new Base;//错误,抽象类无法实例化对象
	base = new Son;
	base->func();
	delete base;//记得销毁
}
	int main()
	{
		test();
	return 0;
	}

五,多态动态化实例2制作饮品

案例描述:

制作饮品的大致流程分为:煮水-冲泡-倒入杯中-加入辅料

利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶;

个人实现代码:

#include<iostream>
using namespace std;
//制作饮品的大致流程分为:煮水 - 冲泡 - 倒入杯中 - 加入辅料
//
//利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶;
class Createdrink
{
public:
	void zhushui()
	{
		cout << "煮水-";
	 }
	void congpao()
	{
		cout << "冲泡-" ;
	}
	virtual void daobei()
	{
		cout << "倒入杯中-" ;
	}
	virtual void fuliao() = 0;
};
class coffee :public  Createdrink {
	virtual void fuliao()
	{
		cout << "加入咖啡" <<endl;
	}

};
class tea :public  Createdrink {
	virtual void fuliao()
	{
		cout << "加入茶叶" << endl;
	}

};
void test1()
{
	Createdrink* base = NULL;
	base = new coffee;
	base->zhushui(); base->congpao(); base->daobei(); base->fuliao();
	delete base;

}
void test2()
{
	Createdrink* base = NULL;
	base = new tea;
	base->zhushui(); base->congpao(); base->daobei(); base->fuliao();
	delete base;

}
int main()
{
	cout << "泡咖啡流程:" << endl;
	test1();
	cout << "泡茶流程:"<<endl;
	test2();

}

效果图:

实例代码:

#include<iostream>
using namespace std;
//制作饮品的大致流程分为:煮水 - 冲泡 - 倒入杯中 - 加入辅料
//
//利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶;
class abstractdrinking {
public:
	virtual void boil() = 0;
	virtual void brew() = 0;
	virtual void pourincup() = 0;
	virtual void putsomething() = 0;
	void makedrink()
	{
		boil();
		brew();
		pourincup();
		putsomething();
	}
};
class coffee :public abstractdrinking {
	virtual void boil() {
		cout << "煮农夫山泉" << endl;
	}
	virtual void brew()
	{
		cout << "冲咖啡" << endl;
	}
	virtual void pourincup() {
		cout << "倒入瓷杯" << endl;
	}
	virtual void putsomething() {
		cout << "加牛奶和糖" << endl;
	}
};
class tea :public abstractdrinking {
	virtual void boil() {
		cout << "煮泉水" << endl;
	}
	virtual void brew()
	{
		cout << "冲茶叶" << endl;
	}
	virtual void pourincup() {
		cout << "倒入玻璃杯" << endl;
	}
	virtual void putsomething() {
		cout << "加柠檬" << endl;
	}
};
void dowork(abstractdrinking* abs)//abstractdrinking*abs=new coffee建立接口
{
	abs->makedrink();
	delete abs;//注意释放
}
void test1()
{
	dowork(new coffee);//连接接口
	cout << "-------------------" << endl;
	dowork(new tea);
}
int main()
{
	test1();
	return 0;
}

效果图:

 六,虚析构和纯虚析构

共性:

1,可以解决父类指针释放子类对象

2,都需要有具体的函数实现

区别:

如果是纯虚析构,该类属于抽象类,无法实例化对象

虚析构语法:

virtual ~类名(){}

纯虚析构语法:

virtual ~类名()=0

类名::~类名(){}

class Animal {
public:
	Animal() {
		cout << "Animal构造函数调用!" << endl;
	}
	virtual void speak() = 0;
	//析构函数加virtual关键字,变为虚析构函数
	//virtual ~Animal(){
	//cout<<"Animal虚构造函数调用!"<<endl;}
	virtual ~Animal() = 0;
};
Animal::~Animal()
{
	cout << "Animal虚构造函数调用!" << endl;
}
//和包含了普通纯虚函数的类一样,包含了纯虚函数的类也是一个抽象类,不能够被实例化
class Cat :public Animal {
public:
	Cat(string name)
	{
		cout << "Cat构造函数调用" << endl;
		m_Name = new string(name);
	}
	virtual void speak()
	{
		cout <<* m_Name<< "小猫在说话!" << endl;
	}
	~Cat()
	{
		cout << "cat析构函数调用" << endl;
		if (this->m_Name != NULL)
		{
			delete m_Name;
			m_Name = NULL;
		}
	}
public:
	string* m_Name;
};
void test() {
	Animal* animal = new Cat("Tom");
	animal->speak();
	delete animal;
}
int main()
{
	test();
	return 0;
}

总结:

1,析构函数或纯虚函数就是用来解决父类指针释放子类对象

2,如果子类中没有堆区数据,可以不写为虚析构或纯虚析构 

3,拥有纯虚析构函数的类也属于抽象函数

七,多态案例三---电脑组装

案例描述:

电脑主要组成部件为CPU,显卡,内存条

将每个零件封装出抽象基类,并且提供不同的厂商生产不同的零件,例如intel

厂商lenovo厂商,创建电脑类提供让电脑工作的函数,并且调用每个零件工作的接口

测试时组装santaibuton

class CPU {
public:
	virtual void calculate() = 0;//注意定义时一定要声明公共访问权限
};
class videoCard {
public:
	virtual void dispalay() = 0;

};
class memory {
public:
	virtual void storage() = 0;
};
//电脑类
class computer {
public:
	//构造函数中传入三个零件指针
	computer(CPU* cpu, videoCard* vc, memory* mem)//构造函数传入指针
	{
		m_cpu = cpu;
		m_vc = vc;
		m_memory = mem;

	}
	void dowork()//建立接口,进行多态,运行派生类的函数
	{
		m_cpu->calculate();
		m_vc->dispalay();
		m_memory->storage();
	}
	~computer()//析构函数清理堆区
	{
		if (m_cpu != NULL)
		{
			delete m_cpu;
			m_cpu = NULL;
		}
		if (m_vc != NULL)
		{
			delete m_vc;
			m_vc = NULL;
		}
		if (m_vc != NULL)
		{
			delete m_vc;
			m_vc = NULL;
		}
	}
    
private:
	CPU* m_cpu;//堆区定义指针维护
	videoCard* m_vc;
	memory* m_memory;

};
//厂商
class intelcpu :public CPU {
	void calculate()
	{
		cout << "intel的cpu开始工作!" << endl;
	}
};
class intelvideoCard :public videoCard {
	void dispalay()
	{
		cout << "intel的显卡开始工作!" << endl;
	}
};
class intelmemory :public memory {
	void storage()
	{
		cout << "intel的内存条开始工作!" << endl;
	}
};
class lenvocpu :public CPU {
	void calculate()
	{
		cout << "lenvo的cpu开始工作!" << endl;
	}
};
class lenvovideoCard :public videoCard {
	void  dispalay()
	{
		cout << "lenvo的显卡开始工作!" << endl;
	}
};
class lenvomemory :public memory {
	void storage()
	{
		cout << "lenvo的内存条开始工作!" << endl;
	}
};
void test()
{
	cout << "创建第一台电脑" << endl;
	computer *c1=new computer(new intelcpu,new intelvideoCard,new intelmemory);//建立指针,传入派生类
	c1->dowork();
	cout << "________________________________" << endl;
	cout << "创建第二台电脑" << endl;
	computer* c2 = new computer(new intelcpu, new lenvovideoCard, new lenvomemory);
	c2->dowork();
}
int main()
{
	test();
	return 0;
}

运行效果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值