C++基础语法 11(多态、纯虚构函数、抽象类)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6


#include<iostream>
using namespace std;
#include<string>

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

//动态多态: 派生类 和 虚函数 实行运行时多态 -----满足条件:!有继承关系!、!子类要重写父类的虚函数!
//使用: 父类 的 指针 或 引用 来指向子类的对象!

//(重载!是函数的名字相同 参数不一样;)(重写!是函数的返回值类型相同 函数名称相同 形参列表当中的所有 内容相同-但是!父类当中是函数一定要变成!虚函数!)

//多态优点:代码组织结构清晰;可读性强;利于前期和后期的维护

//静态多态和动态多态的区别:静态多态的函数地址早绑定 - 编译阶段 确定函数的地址!
//动态多态的函数地址晚绑定 - 运行阶段 确定函数的地址!


//动态多态

//class Animal //动物类
//{
//public:
// //说话的行为 -----非静态的成员函数 不属于类的对象上
// 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) //在C++当中允许 父类 - 子类当中的类型转换!父类的指针/引用可以直接指向子类的对象!
////{
//// animal.speak(); //动物在说话! 因为传入的是一个 Animal对象引用 不管传入的是什么类型的子类都访问的是 Animal这个类当中的函数!!!!!!!!!!
////}
//
////!!!!!如果想执行让猫说话,这个地址就不能提前绑定,需要在运行阶段进行绑定,也就是 地址晚绑定!!!!!
////在Animal 当中的 void speak() 函数前面加上!!!!!virtual !!!!! 使得其成为 虚函数 以实现地址晚绑定!
//void doSpeak(Animal &animal)
//{
// animal.speak(); //喵喵喵
//}
//
//
//void test01()
//{
// Cat cat; //创建的是一个猫的对象 但是传入函数体当中的是 Animal的对象,相当于父类的引用在接收子类的对象!
// doSpeak(cat);
//
// Dog dog;
// doSpeak(dog);
//}
//
//void test02()
//{
// cout << "sizeof Animal= " << sizeof(Animal) << endl;//没加virtual 时1 只有一个非静态的成员函数 不属于类的对象上 相当于空类
// //加上virtual 后 4 类的内部多了一个“虚函数(表)指针vftable”;表内部会记录一个虚函数地址
// //当进行了子类重写了父类的虚函数 子类的继承的虚函数表内部会替换成子类的虚函数地址!见图!!!!!但是父类当中的表内容没有发生改变!
//}
//int main()
//{
// //test01();
// test02();
// return 0;
//}




//案例1-计算机类 :利于普通写法和多态技术,设计实现两个操作数进行运算的计算机类

//1、普通写法实现:

//class Culculator
//{
//public:
// int getResult(string oper)//获取运算结果
// {
// if (oper == "+")
// {
// return m_Num1 + m_Num2;
// }
// else if (oper == "-")
// {
// return m_Num1 - m_Num2;
// }
// else if (oper == "*")
// {
// return m_Num1 * m_Num2;
// }
// else if (oper == "/")
// {
// return m_Num1 / m_Num2;
// }
// //想扩张新的功能,需要修改源码;在真实的开发当中提倡:开闭原则!!!!!(对扩张进行开放,对修改进行关闭)!!!!!-利用多态实现
//
// }
//
// int m_Num1;//操作数1/2
// int m_Num2;
//};
//void test01()
//{
// //创建计算器对象
// Culculator c;
// c.m_Num1 = 100;
// c.m_Num2 = 9;
//
// 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;
// cout << c.m_Num1 << "/" << c.m_Num2 << "=" << c.getResult("/") << endl;
//}

//2、利用多态实现计算器-----代码量虽然大了,但是组织机构清晰!!!!!并且可读性强

//先实现计算器的抽象类!(什么功能都不实现)

//class AbstractCalculator
//{
//public:
// virtual int getResult() //父类当中设置虚函数 方便下面进行子类的函数覆盖!
// {
// return 0;
// }
// int m_Num1;
// int m_Num2;
//};
// //设计加法 计算器功能的实现
//class AddCalculator :public AbstractCalculator
//{
//public:
// int getResult() //子类当中重新写出 要实现的函数功能!
// {
// return m_Num1 + m_Num2;
// }
//};
// //设计减法 计算器功能的实现
//class SubCalculator :public AbstractCalculator
//{
//public:
// int getResult()
// {
// return m_Num1 - m_Num2;
// }
//};
// //设计乘法 计算器功能的实现
//class MulCalculator :public AbstractCalculator
//{
//public:
// int getResult()
// {
// return m_Num1 * m_Num2;
// }
//};
//void test02()
//{
// //多态的使用 条件:父类的指针或引用来指向子类的对象 -动态多态当中描述了 引用 下面描述 指针
//
// //加法运算
// AbstractCalculator *abc = new AddCalculator;//创建一个加法对象!?可以不在堆区吗? 答,不能:因为指针要返回的是 地址 !!!!!
// abc->m_Num1 = 10;
// abc->m_Num2 = 90;
//
// cout << abc->m_Num1 << "+" << abc->m_Num2 << "=" << abc->getResult() << endl;
// //因为在堆区 用完后 记得释放堆区!
// delete abc;//只是把堆区的数据释放了 指针的类型是没有改变的!
//
// //减法
// abc = new SubCalculator;
// abc->m_Num1 = 10;
// abc->m_Num2 = 90;
// cout << abc->m_Num1 << "-" << abc->m_Num2 << "=" << abc->getResult() << endl;
// delete abc;
//
// //乘法
// abc = new MulCalculator;
// abc->m_Num1 = 10;
// abc->m_Num2 = 90;
// cout << abc->m_Num1 << "*" << abc->m_Num2 << "=" << abc->getResult() << endl;
// delete abc;
//
//}
//int main()
//{
// //test01();
// test02();
// return 0;
//}




//纯虚函数和抽象类:在多态当中,常常父类当中的虚函数是毫无意义的,主要是实现调用子类的类的重写的内容;所以父类将虚函数称为纯虚函数!
//纯虚函数语法:virtual 返回类型 函数名称 (参数列表) =0;//(不需要写{return0;}那些了)
//当类当中有了 !纯虚函数! 这个类被称为 -----抽象类!:特点 1、无法实例化对象;2、子类必须重写抽象类当中的纯虚函数,否则也属于抽象类!

//class Base
//{
//public:
// virtual void func() = 0;//纯虚函数-----在虚函数的基础上=0;因为存在纯虚函数,所以这个父类也叫—“抽象类”
//
//};
//class Son:public Base
//{
//public:
// void func()
// {
// cout << "函数的调用" << endl;
// }
//};
//void yy(Base &base)
//{
// base.func();
//}
//void test01()
//{
// //Base a; //报错 纯虚函数不能实例化对象!在堆区也不行
// //Son b; //在子类当中没有重写父类当中的 纯虚函数时 编译器也会报错!
// //Son c;//子类当中重写了纯虚函数 编译器就不会发生报错了!
//
// /*Son d; //引用调用
// yy(d);*/
//
// Base *base = new Son; //指针调用!
// base->func();
//}
//int main()
//{
// test01();
// return 0;
//}

//案例2-制作饮品:煮水-冲泡-倒入杯中-加入调料

//利用多态类实现,提供抽象类制作饮品基类,提供子类制作咖啡和茶类class AbstractDrinkong

{

public:

//煮水

virtual void Boil() = 0;

//冲泡

virtual void Brew() = 0;

//倒入杯中

virtual void PourInCup() = 0;

//加入调料

virtual void Putsome() = 0;//制作饮品-总体实现-调用一次就能实现这四个步骤
void makeDrink()
{
Boil();
Brew();
PourInCup();
Putsome();
}};

//制作咖啡

class Coffee:public AbstractDrinkong

{

public:

//子类当中必须重写父类的纯虚函数

//煮水

virtual void Boil()

{

cout << "煮泉水" << endl;

}

//冲泡

virtual void Brew()

{

cout << "冲泡咖啡" << endl;

}

//倒入杯中

virtual void PourInCup()

{

cout << "倒入杯中" << endl;

}

//加入调料

virtual void Putsome()

{

cout << "加入牛奶" << endl;

}

};

//制作茶

class Tea :public AbstractDrinkong

{

public:

//煮水

virtual void Boil()

{

cout << "煮泉水" << endl;

}

//冲泡

virtual void Brew()

{

cout << "冲泡茶" << endl;

}

//倒入杯中

virtual void PourInCup()

{

cout << "倒入杯中" << endl;

}

//加入调料

virtual void Putsome()

{

cout << "加入果汁" << endl;

}

};

//操作函数

void doWork(AbstractDrinkong *abs) //父类指针调用子类函数 AbstractDrinkong *abs=new coffee;

{

abs->makeDrink(); //一调用它传入子类的类型即可以实现子类的函数!

delete abs;//因为在堆区 所以要及时的 是否堆区的数据!!!!!

}

void test01()

{

cout << "制作咖啡" << endl;

doWork(new Coffee);//因为是用指针传递的 所以是在堆区创建的!!!!!
cout << "--------------------------------------" << endl;
cout << "制作茶" << endl;
doWork(new Tea);//因为是用指针传递的 所以是在堆区创建的!!!!!
}

int main()

{

test01();

return 0;

}


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++