12.1 多态概念12.1.1 多态基本概念12.1.2 多态案例12.1.3 多态的分类12.2 多态和虚函数12.2.1 虚函数和抽象类12.2.2 虚函数VS纯虚函数12.2.3 虚析构和纯虚析构12.4 动态绑定12.4.1 理解动态绑定12.4.2 动态绑定案例12.5 多态应用场景 #技术分享12.5.1 接口设计12.5.2 扩展性12.5.3 代码复用12.5.4 多态总结12.7 多态综合案例12.7.1 计算器类12.7.2 制作饮品12.7.3 组装电脑摘要:前者主要是指函数的重载(包括运算符的重载)、对重载函数的调用,在编译时就能根据实参确定应该调用哪个函数,因此叫编译时的多态;后者则和继承、虚函数等概念有关。
在 C++ 中,多态 是面向对象编程(OOP)的核心特性之一,它允许通过基类的指针或引用调用派生类的重写函数,从而实现“一个接口,多种实现”的效果。
面向对象程序设计语言有封装、继承和多态三种机制,这三种机制能够有效提高程序的可读性、可扩充性和可重用性。
“多态(polymorphism)”指的是同一名字的事物可以完成不同的功能。
多态(polymorphism) :同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
多态可以分为编译时的多态和运行时的多态。
前者主要是指函数的重载(包括运算符的重载)、对重载函数的调用,在编译时就能根据实参确定应该调用哪个函数,因此叫编译时的多态;后者则和继承、虚函数等概念有关。总结:多态满足条件
有继承关系子类重写父类中的虚函数多态使用条件
父类指针或引用指向子类对象
重写:函数返回值类型 函数名 参数列表 完全一致称为重写
public: void eat { cout在多态中,通常父类中虚函数的实现是毫无意义的,主要都是调用子类重写的内容。因此可以将虚函数改为纯虚函数
纯虚函数语法:virtual 返回值类型 函数名 (参数列表)= 0 ;,纯虚函数是通过在声明中使用 "= 0" 来指定的。
如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。
抽象类特点:
无法实例化对象子类必须重写抽象类中的纯虚函数,否则也属于抽象类public: virtual void func = 0;virtual void foo { cout func; base->foo; }int main { test; return 0; }由此可知:
抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。
虚函数(Virtual Function)和纯虚函数(Pure Virtual Function)是面向对象编程中的重要概念,用于实现多态性和抽象类。
虚函数是在基类中声明为虚拟的成员函数,它可以在派生类中被重写(覆盖)。通过使用虚函数,可以在运行时根据对象的实际类型来调用相应的函数实现,实现多态性。纯虚函数是在基类中声明为纯虚拟的成员函数,它没有函数体,只有函数声明,并且使用= 0来指示。纯虚函数在基类中没有默认实现,它的具体实现由派生类提供。纯虚函数用于定义抽象类,它不能被实例化,只能作为基类来派生其他类。以下是虚函数和纯虚函数的示例:
public: virtual void virtualFunction { std::cout pureVirtualFunction; derived2->virtualFunction; return 0; }虚函数和纯虚函数都可以通过指针或引用来实现运行时多态性,即在运行时根据对象的实际类型来调用相应的函数实现。
多态使用时,如果子类中有属性开辟到堆区,那么父类指针在释放时无法调用到子类的析构代码
解决方式:将父类中的析构函数改为虚析构或者纯虚析构
虚析构和纯虚析构共性:
可以解决父类指针释放子类对象都需要有具体的函数实现虚析构和纯虚析构区别:如果是纯虚析构,该类属于抽象类,无法实例化对象
虚析构语法:virtual ~类名{}
纯虚析构语法:virtual ~类名 = 0;
类名::~类名{}
public: Animal { cout name2 != NULL) { delete name2; name2 = NULL; } } };int main { Animal *animal = new Cat("Tom"); animal->speak; animal->eat; animal->play; delete animal; return 0; }打印结果如下所示:
Animal 构造函数调用!Cat 构造函数调用!TomCat1 在说话!TomCat2 在说话!TomCat1 在吃东西!TomCat2 在吃东西!Animal 动物在玩!Cat析构函数调用!Animal虚析构函数调用!总结:
虚析构或纯虚析构就是用来解决通过父类指针释放子类对象如果子类中没有堆区数据,可以不写为虚析构或纯虚析构拥有纯虚析构函数的类也属于抽象类通过利用虚函数实现动态绑定,可以在运行时根据对象的实际类型来调用相应的函数,实现多态的效果。
这提供了更灵活和可扩展的代码结构,使得程序能够适应不同类型的对象并执行相应的操作。
public: virtual void draw { cout draw;shape = &rectangle; shape->draw; return 0; }案例描述:分别利用普通写法和多态技术,设计实现两个操作数进行运算的计算器类
多态的优点:
代码组织结构清晰可读性强利于前期和后期的扩展以及维护示例:普通写法
public: int getResult(string oper) { if (oper == "+") { return num1 + num2; } else if (oper == "-") { return num1 - num2; } else if (oper == "*") { return num1 * num2; } return 0; } public: int num1; int num2; };void test01 { Calculator c; c.num1 = 10; c.num2 = 10; cout示例:多态技术
class AbstractCalculator {public : virtual int getResult { return 0; }int num1; int num2; };class AddCalculator : public AbstractCalculator { public: int getResult { return num1 + num2; } };class SubCalculator : public AbstractCalculator { public: int getResult { return num1 - num2; } };class MulCalculator : public AbstractCalculator { public: int getResult { return num1 * num2; } };void test02 { AbstractCalculator *abc = new AddCalculator; abc->num1 = 10; abc->num2 = 10; cout num1 num2 getResult num1 = 10; abc->num2 = 10; cout num1 num2 getResult num1 = 10; abc->num2 = 10; cout num1 num2 getResult案例描述:
制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料
利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡,茶叶,奶茶等。
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 { public: virtual void Boil { cout MakeDrink; }void test { DoWork(new Coffee); cout打印结果如下所示:
煮农夫山泉!冲泡咖啡!将咖啡倒入杯中!加入牛奶!冲泡茶叶! 将茶水倒入杯中! 加入枸杞!#includeusing namespace std;class CPU { public: virtual void calculate = 0; };class VideoCard { public: virtual void display = 0; };class Memory { public: virtual void storage = 0; };class Computer { public: Computer(CPU *{ m_cpu = cpu; m_vc = vc; m_mem = mem; }void work { m_cpu->calculate;m_vc->display;m_mem->storage; }~Computer {if (m_cpu != NULL) { delete m_cpu; m_cpu = NULL; }if (m_vc != NULL) { delete m_vc; m_vc = NULL; }if (m_mem != NULL) { delete m_mem; m_mem = NULL; } }private:CPU *VideoCard *Memory *};class IntelCPU :public CPU { public: virtual void calculate { cout work; delete computer1;cout work; delete computer2;cout work; delete computer3;}来源:墨码行者