当前位置:首页 > 芯闻号 > 充电吧
[导读]    多态性是C++的一个重要特征。从广义上说,多态性是指一段程序能够处理多种类型对象的能力;具体地讲,多态性就是对不同对象发出同样的指令时,不同对象会有不同的行为。    



    多态性是C++的一个重要特征。从广义上说,多态性是指一段程序能够处理多种类型对象的能力;具体地讲,多态性就是对不同对象发出同样的指令时,不同对象会有不同的行为。
    如果程序员充分利用C++的多态性,设计程序的运行方式会更加灵活多样,但是会带来一些暗藏的细节问题。这些细节的漏洞也许会通过编译,但是在某些情况下,不可预测的结果或者背离编程者初衷的结果都会导致程序变得混乱不堪,甚至产生较大的风险。为了规避这些风险,MISRA C++推荐了一些编程规则。这些规则能够帮助程序员更加完备或者完美地实现多态性,充分体现C++相比于传统C语言的一些优势。
    本文主要介绍两类在实现形式的多态性中需要注意的一些问题:一是运算符的重载,这是编译时的多态性,即程序在编译时就能根据重载的情况确定需要调用的函数;二是虚函数的使用,这是运行时的多态性,即在程序执行前,无法根据函数名和参数来确定调用哪个函数,必须在程序执行过程中,根据执行的具体情况来动态确定。


1 运算符的重载
    运算符重载就是定义某个运算符对于某个类的具体含义。通过运算符的重载,程序员可以针对一些特定的类型使用重载的运算符含义。
    规则5-2-11(强制):逗号(,),与(&&)以及或(||)运算符不允许被重载。


    如果getValue和setValue的返回类型使用重载运算符&&,则这两个函数都需要计算。
    C++的内部规定是,&&和||都是在已知结果的情况下不再计算后面的值,比如0&&(a--)&&(b++)。然而重载&&运算符和||运算符导致了程序运行时要计算所有的表达式。这对于一些使用&&做判断的运算来说,会导致一些错误。比如getchar()&&putchar(),在读取文件时,如果读到文件尾部,即得到getchar()为0时,就不需要再执行putchar()了,这样才能正确地读取并输出文件。如果重载&&运算符,那么先需要计算getchar()和putchar()的结果,再执行&&运算符的重载定义,这样可能会导致一些不可知的错误。这样的重载,会导致编译器在处理&&和||运算符时产生混乱,所以是比较危险的。
    对于逗号表达式来说,默认情况下,编译器按照逗号表达式规定的顺序计算各个表达式。但是如果重载操作逗号表达式,因为需要先检查逗号两边的表达式类型,来判断是否使用重载定义的类型,所以会导致计算顺序的混乱。这样比较危险,会产生一些不可知的错误。虽然在C++并没有限制这3个运算符的重载问题,但是从这个例程和MISRA C++的规则来看,有些时候会产生一些不可预知的错误,所以MISRA C++不允许重载上面3个运算符。[!--empirenews.page--]
    规则5-3-3(强制):单目运算符&不允许被重载。

    
    f1.cc和f2.cc的区别就在于f1.cc只声明了A类,而f2.cc包含了A.h。f1.cc仅声明A类,不会使用A类定义的重载运算,所以f1.cc的8L运算符使用C++内部的取地址定义。f2.cc包含了头文件A.h,因为A.h包含了A类的完整定义,所以f2.cc的&运算符就会使用用户定义的重载操作。在同样一个工程中,仅仅是对A类的声明不同,就导致了在f2.cc中,&a使用用户定义的&运算符含义,而在f1.cc中,&a使用C++内部定义的&运算符含义。
    这样差别会导致程序员在重载&运算符后,无法得知&运算符有没有使用重载的定义。这样做是比较危险的,可能会产生与程序员意愿不同的结果。虽然在C++中并没有限制对单目运算符的重载操作,但是从上面的例程可以看出,MISRA C++不允许重载&运算符是很有必要的。


2 虚函数的使用
    虚函数是C++中一类特殊的函数。在基类中定义一个虚函数,就说明该函数在派生类中可能有不同的实现方式。当派生类的实例调用这个虚函数时,首先会在派生类中去查看该函数有没有被定义。如果派生类定义了这个函数,则执行派生类的函数;否则,在派生路径上寻找最近的该函数的定义,并调用该函数。
    如果从基类派生出多个派生类,那么每个派生类都可以重新定义这个虚函数。如果通过基类的指针指向派生类的对象,并访问该虚函数,会对应地调用每个派生类的函数定义。这样通过基类类型的指针,就可以使属于不同派生类的对象产生不同的行为,从而实现了运行过程的多态。[!--empirenews.page--]
    关于虚函数,MISRA C++有以下几条规则:
    规则10-3-1(强制):在每一个继承路径上,虚函数只能有一个定义。防止按优先度调用。
    例外:析构函数可以定义为虚函数,在每一个派生类上都可以有定义。
    如果一个函数在同一个类中被声明为纯虚函数,但是还有定义,这样的定义就会被忽略。

    


    

    
    在例程的后半段是关于按优先度调用的解释,表1显示的是例程中每个函数的调用和定义关系。b2.f1()是按照正常的继承关系来调用foo()函数,并且调用的是V类中foo()的定义。d.f2()和d.f1()都是按照优先度调用的。它们虽然最后都是调用了foo()函数,但是经过的继承路径却不相同,而且它们最后只能调用到B1类中foo()的定义。为了防止这种情况发生,所以Misra C++规定,虚函数在一个继承路径上,只能有一个函数定义。



    例程的前半部分描述了多个类的继承关系,每个类都包括对几个函数的定义和声明。这里简单介绍一下f1()函数,读者可以通过表2的内容来理解其他函数。f1在A类中是虚函数,而且有定义,在C类中有定义,所以当D类继承C类时,D类中就不能再有定义(“√”表示可以定义,“*”表示不推荐再继续定义)。例外是f4,虽然它在A类中有定义,但是因为它是纯虚函数,所以它的定义会被忽略。



    这个规则说明,如果在一个继承路径上有两个函数定义,在调用函数时,有可能按照继承的优先度调用函数。这样就会导致函数调用的混乱,可能会调不到程序员希望的函数。这是在实现多态时需要特别注意的地方。关于继承路径上的函数定义,C++并没有明确限制。[!--empirenews.page--]
   从上面的例程可以看出,如果没有这样的限制,就会产生一些混乱,虽然程序能够正常运行,但是不一定能够按照程序员所设计的方式运行。这样的运行方式会出现很多漏洞,所以MISRA C++强制规定在每一个继承路径上,虚函数只能有一个定义。
    规则10-3-2(强制):每一个重载的虚函数应该用关键字virtual来声明。

    
    这样做不需要检查基类,就可以确定函数是否为虚函数。MISRA C++推出这样的规则是为了使C++程序更加完善。
    规则10-3-3(强制):只有被声明为纯虚函数的虚函数,才能被纯虚函数重载。

    
    foo函数在A类中定义为纯虚函数,在B类中被重载为普通虚函数。而C类使用纯虚函数重载foo函数。这样做是不行的。
    B类中foo函数重载A类的foo函数时,是用有定义的虚函数重载纯虚函数,这样做是可以的。
    C类中的foo函数重载B类的foo函数时,是用纯虚函数重载一个非纯虚函数,这样是不行的。在C类中,foo被定义为纯虚函数,在C类的对象调用foo函数时无法调用到B类中的定义。这样的重载导致B类中对foo函数的定义丢失。
    所以MISRA C++不允许使用纯虚函数重载非纯虚函数,这样做的目的也是为了使C++程序更加安全。


3 小 结
    正确并完备地实现C++的多态性,能够充分发挥C++的优势,并且提高程序的可读性和可维护性。如果使用不当,会导致一些想象不到的程序漏洞。MISRA C++针对使用多态性可能产生的一些漏洞,提出了规避的方法与建议。本文列出了其中几条比较关键和实用的规则。关于多态性的其他规则,读者可以查看。MISRA C++(2008),以避免不正确使用多态性所导致的一些程序漏洞。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭