news 2026/6/15 13:27:52

C++之多态及虚函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++之多态及虚函数

文章目录

  • 多态
  • 虚函数

多态

  • 多态性是面向对象程序设计语言的又一重要特征,多态(polymorphism)通俗地讲,就是用一个相同的名字定义许多不同的函数,这些函数可以针对不同数据类型实现相同或相似的功能,即所谓的“一个接口,多种实现”
#include<iostream>usingnamespacestd;classShape{public:virtualvoiddraw(void){cout<<"draw shape"<<endl;}};classRect:publicShape{public:voiddraw(void){cout<<"draw Rect"<<endl;}};classCircle:publicShape{public:voiddraw(void){cout<<"draw Circle"<<endl;}};classEllipse:publicShape{public:voiddraw(void){cout<<"draw Ellipse"<<endl;}};intmain(void){/* Ellipse e; e.draw(); e.Shape::draw(); */Shape*buf[128]={0};buf[0]=newRect;buf[1]=newCircle;buf[2]=newEllipse;for(inti=0;buf[i]!=NULL;i++){buf[i]->draw();}return0;}

虚函数

  • 被virtual关键字修饰的成员函数称为虚函数
  • 如果将基类中的某个成员函数声明为虚函数,那么子类中与该函数具有相同原型的成员函数就也是虚函数,并且对基类中版本形成覆盖,即函数重写
  • 如果子类提供了对基类虚函数有效的覆盖,那么通过指向子类对象的基类指针,或者通过引用子类对象基类引用,调用该虚函数,实际被执行将是子类中的覆盖版本,而不再是基类中原始版本,这种语法现象被称为多态
  • 多态的意义在于,一般情况下,调用哪个类的成员函数由调用者指针或者引用本身类型决定的, 而有了多态,调用哪个类的成员函数由调用者指针或者引用实际目标对象的类型决定
  • 这样一来,源自同一种类型的同一种激励,竟然可以产生多种不同的响应,也就是对于同一个函数调用,能够表达出不同的形态,即为多态
  • 虚函数覆盖的条件:
    • 只有类中的成员函数才能声明为虚函数,而全局函数、静态成员函数、构造函数都不能被声明为虚函数
    • 只有在基类中以virtual关键字声明的虚函数,才能作为虚函数被子类覆盖,而与子类中的virtual关键字无关
    • 虚函数在子类中的版本和基类中版本要具有相同的函数签名,即函数名、参数表、常属性一致
    • 如果基类虚函数返回基本类型的数据,那么子类中的版本必须返回相同类型的数据;如果基类虚函数返回类类型指针(A)或引用(A&),那么允许子类中的版本返回其子类类型指针(B)或引用(B&)
#include<iostream>usingnamespacestd;classA{};classB:publicA{};classBase{public:virtualvoidfunc(void){cout<<"Base func"<<endl;}virtualA*foo(void){cout<<"Base foo"<<endl;}};classDerived:publicBase{voidfunc(void){cout<<"Derived func"<<endl;}B*foo(void){cout<<"Derived foo"<<endl;}};intmain(void){Derived d1;Base*pd1=&d1;pd1->func();Base&pd2=d1;pd2.foo();return0;}
  • 产生多态的条件:
    • 除了要满足函数重写的语法要求,还必须是通过指针或引用调用虚函数,才能表现出来
#include<iostream>usingnamespacestd;classA{};classB:publicA{};classBase{public:virtualvoidfunc(void){cout<<"Base func"<<endl;}virtualA*foo(void){cout<<"Base foo"<<endl;}};classDerived:publicBase{voidfunc(void){cout<<"Derived func"<<endl;}B*foo(void){cout<<"Derived foo"<<endl;}};intmain(void){Derived d1;Base b=d1;b.func();//实际上调用 base中的funcreturn0;}
  • 调用虚函数的指针也可以是this指针,当使用子类对象调用基类中的成员函数时,该函数里面this指针将是一个指向子类对象的基类指针,再通过this去调用满足重写要求的虚函数同样可以表现多态的语法特性
#include<iostream>usingnamespacestd;classA{};classB:publicA{};classBase{public:virtualvoidfunc(void){cout<<"Base func"<<endl;}A*foo(void){//this->func();func();}};classDerived:publicBase{voidfunc(void){cout<<"Derived func"<<endl;}};intmain(void){Derived d1;d1.foo();return0;}
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/20 23:13:01

2026 CRM终局之战:生态定胜负,AI决输赢

CRM软件被AI重写&#xff0c;竞争也演进为生态体系之争。 文&#xff5c;牛慧 编&#xff5c;赵艳秋 2025年底一组关键数据引发业内关注&#xff1a;美国市场AI调用量最高的并非互联网或手机助手平台&#xff0c;而是SaaS企业。其中SAP、Salesforce已跻身OpenAI最核心客户群…

作者头像 李华
网站建设 2026/6/4 22:36:59

万物皆有意义:活出个体精彩与意义信仰的实践框架

万物皆有意义&#xff1a;活出个体精彩与意义信仰的实践框架一、意义的双重性&#xff1a;普遍性与独特性万物皆有意义&#xff0c;但意义呈现方式因人而异——这是个体精彩得以存在的前提。如同阳光普照大地&#xff0c;但每朵花以独特方式绽放&#xff1b;海洋滋养万物&#…

作者头像 李华
网站建设 2026/6/10 0:49:09

如何安全轻松地出售损坏的 iPhone

即使你的 iPhone 破裂、进水或无法开机&#xff0c;它仍然有价值。出售损坏的 iPhone 既能帮你赚点外快&#xff0c;还能清理杂物。然而&#xff0c;在出售你的 iPhone 之前&#xff0c;有几个重要因素需要考虑。从确保数据安全到找到合适的买家&#xff0c;本指南将指导你完成…

作者头像 李华
网站建设 2026/6/9 20:44:42

零基础学 HBuilderX?先看这篇超详细安装教程,入门到精通一篇搞定

一、下载安装 1.在地址栏中直接输入https://www.dcloud.io 2.点击箭头所指&#xff0c;进去过后点击DOWNLOAD。 3.点击过后 选择自己所需要的版本。 HBuilder目前有两个版本&#xff0c;一个是windows版&#xff0c;一个是mac版。下载的时候根据自己的电脑选择适合自己的版本…

作者头像 李华
网站建设 2026/6/4 14:22:57

使用 OpenTelemetry 和 Elastic Streams 进行 Windows 事件日志监控

作者&#xff1a;来自 Elastic David Hope 学习如何使用 OpenTelemetry 提升 Windows 事件日志监控&#xff0c;实现标准化摄取&#xff0c;并使用 Elastic Streams 进行智能分区和分析。 对于系统管理员和 SRE 来说&#xff0c;Windows 事件日志既是金矿也是坟场。它们包含诊断…

作者头像 李华