0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

MISRA C++針對(duì)使用多態(tài)性的規(guī)避方法與建議

電子設(shè)計(jì) ? 來(lái)源:?jiǎn)纹瑱C(jī)與嵌入式系統(tǒng)應(yīng)用 ? 作者:王璽 , 邵貝貝 ? 2020-09-07 18:41 ? 次閱讀

多態(tài)性是C++的一個(gè)重要特征。從廣義上說(shuō),多態(tài)性是指一段程序能夠處理多種類型對(duì)象的能力;具體地講,多態(tài)性就是對(duì)不同對(duì)象發(fā)出同樣的指令時(shí),不同對(duì)象會(huì)有不同的行為。

如果程序員充分利用C++的多態(tài)性,設(shè)計(jì)程序的運(yùn)行方式會(huì)更加靈活多樣,但是會(huì)帶來(lái)一些暗藏的細(xì)節(jié)問(wèn)題。這些細(xì)節(jié)的漏洞也許會(huì)通過(guò)編譯,但是在某些情況下,不可預(yù)測(cè)的結(jié)果或者背離編程者初衷的結(jié)果都會(huì)導(dǎo)致程序變得混亂不堪,甚至產(chǎn)生較大的風(fēng)險(xiǎn)。為了規(guī)避這些風(fēng)險(xiǎn),MISRA C++推薦了一些編程規(guī)則。這些規(guī)則能夠幫助程序員更加完備或者完美地實(shí)現(xiàn)多態(tài)性,充分體現(xiàn)C++相比于傳統(tǒng)C語(yǔ)言的一些優(yōu)勢(shì)。

本文主要介紹兩類在實(shí)現(xiàn)形式的多態(tài)性中需要注意的一些問(wèn)題:一是運(yùn)算符的重載,這是編譯時(shí)的多態(tài)性,即程序在編譯時(shí)就能根據(jù)重載的情況確定需要調(diào)用的函數(shù);二是虛函數(shù)的使用,這是運(yùn)行時(shí)的多態(tài)性,即在程序執(zhí)行前,無(wú)法根據(jù)函數(shù)名和參數(shù)來(lái)確定調(diào)用哪個(gè)函數(shù),必須在程序執(zhí)行過(guò)程中,根據(jù)執(zhí)行的具體情況來(lái)動(dòng)態(tài)確定。

1 運(yùn)算符的重載

運(yùn)算符重載就是定義某個(gè)運(yùn)算符對(duì)于某個(gè)類的具體含義。通過(guò)運(yùn)算符的重載,程序員可以針對(duì)一些特定的類型使用重載的運(yùn)算符含義。

規(guī)則5-2-11(強(qiáng)制):逗號(hào)(,),與(&&)以及或(||)運(yùn)算符不允許被重載。

如果getValue和setValue的返回類型使用重載運(yùn)算符&&,則這兩個(gè)函數(shù)都需要計(jì)算。

C++的內(nèi)部規(guī)定是,&&和||都是在已知結(jié)果的情況下不再計(jì)算后面的值,比如0&&(a--)&& (b++)。然而重載&&運(yùn)算符和||運(yùn)算符導(dǎo)致了程序運(yùn)行時(shí)要計(jì)算所有的表達(dá)式。這對(duì)于一些使用&&做判斷的運(yùn)算來(lái)說(shuō),會(huì)導(dǎo)致一些錯(cuò)誤。比如getchar()&&putchar(),在讀取文件時(shí),如果讀到文件尾部,即得到getchar()為0時(shí),就不需要再執(zhí)行putchar()了,這樣才能正確地讀取并輸出文件。如果重載&&運(yùn)算符,那么先需要計(jì)算getchar()和 putchar()的結(jié)果,再執(zhí)行&&運(yùn)算符的重載定義,這樣可能會(huì)導(dǎo)致一些不可知的錯(cuò)誤。這樣的重載,會(huì)導(dǎo)致編譯器在處理&&和||運(yùn)算符時(shí)產(chǎn)生混亂,所以是比較危險(xiǎn)的。

對(duì)于逗號(hào)表達(dá)式來(lái)說(shuō),默認(rèn)情況下,編譯器按照逗號(hào)表達(dá)式規(guī)定的順序計(jì)算各個(gè)表達(dá)式。但是如果重載操作逗號(hào)表達(dá)式,因?yàn)樾枰葯z查逗號(hào)兩邊的表達(dá)式類型,來(lái)判斷是否使用重載定義的類型,所以會(huì)導(dǎo)致計(jì)算順序的混亂。這樣比較危險(xiǎn),會(huì)產(chǎn)生一些不可知的錯(cuò)誤。雖然在C++并沒(méi)有限制這3個(gè)運(yùn)算符的重載問(wèn)題,但是從這個(gè)例程和MISRA C++的規(guī)則來(lái)看,有些時(shí)候會(huì)產(chǎn)生一些不可預(yù)知的錯(cuò)誤,所以MISRA C++不允許重載上面3個(gè)運(yùn)算符。

規(guī)則5-3-3(強(qiáng)制):?jiǎn)文窟\(yùn)算符&不允許被重載。

f1.cc和f2.cc的區(qū)別就在于f1.cc只聲明了A類,而f2.cc包含了A.h。f1.cc僅聲明A類,不會(huì)使用A類定義的重載運(yùn)算,所以 f1.cc的8L運(yùn)算符使用C++內(nèi)部的取地址定義。f2.cc包含了頭文件A.h,因?yàn)锳.h包含了A類的完整定義,所以f2.cc的&運(yùn)算符就會(huì)使用用戶定義的重載操作。在同樣一個(gè)工程中,僅僅是對(duì)A類的聲明不同,就導(dǎo)致了在f2.cc中,&a使用用戶定義的&運(yùn)算符含義,而在f1.cc中,&a使用C++內(nèi)部定義的&運(yùn)算符含義。

這樣差別會(huì)導(dǎo)致程序員在重載&運(yùn)算符后,無(wú)法得知&運(yùn)算符有沒(méi)有使用重載的定義。這樣做是比較危險(xiǎn)的,可能會(huì)產(chǎn)生與程序員意愿不同的結(jié)果。雖然在C++中并沒(méi)有限制對(duì)單目運(yùn)算符的重載操作,但是從上面的例程可以看出,MISRA C++不允許重載&運(yùn)算符是很有必要的。

2 虛函數(shù)的使用

虛函數(shù)是C++中一類特殊的函數(shù)。在基類中定義一個(gè)虛函數(shù),就說(shuō)明該函數(shù)在派生類中可能有不同的實(shí)現(xiàn)方式。當(dāng)派生類的實(shí)例調(diào)用這個(gè)虛函數(shù)時(shí),首先會(huì)在派生類中去查看該函數(shù)有沒(méi)有被定義。如果派生類定義了這個(gè)函數(shù),則執(zhí)行派生類的函數(shù);否則,在派生路徑上尋找最近的該函數(shù)的定義,并調(diào)用該函數(shù)。

如果從基類派生出多個(gè)派生類,那么每個(gè)派生類都可以重新定義這個(gè)虛函數(shù)。如果通過(guò)基類的指針指向派生類的對(duì)象,并訪問(wèn)該虛函數(shù),會(huì)對(duì)應(yīng)地調(diào)用每個(gè)派生類的函數(shù)定義。這樣通過(guò)基類類型的指針,就可以使屬于不同派生類的對(duì)象產(chǎn)生不同的行為,從而實(shí)現(xiàn)了運(yùn)行過(guò)程的多態(tài)。

關(guān)于虛函數(shù),MISRA C++有以下幾條規(guī)則:

規(guī)則10-3-1(強(qiáng)制):在每一個(gè)繼承路徑上,虛函數(shù)只能有一個(gè)定義。防止按優(yōu)先度調(diào)用。

例外:析構(gòu)函數(shù)可以定義為虛函數(shù),在每一個(gè)派生類上都可以有定義。

如果一個(gè)函數(shù)在同一個(gè)類中被聲明為純虛函數(shù),但是還有定義,這樣的定義就會(huì)被忽略。

在例程的后半段是關(guān)于按優(yōu)先度調(diào)用的解釋,表1顯示的是例程中每個(gè)函數(shù)的調(diào)用和定義關(guān)系。b2.f1()是按照正常的繼承關(guān)系來(lái)調(diào)用foo()函數(shù),并且調(diào)用的是V類中foo()的定義。d.f2()和d.f1()都是按照優(yōu)先度調(diào)用的。它們雖然最后都是調(diào)用了foo()函數(shù),但是經(jīng)過(guò)的繼承路徑卻不相同,而且它們最后只能調(diào)用到B1類中foo()的定義。為了防止這種情況發(fā)生,所以Misra C++規(guī)定,虛函數(shù)在一個(gè)繼承路徑上,只能有一個(gè)函數(shù)定義。

例程的前半部分描述了多個(gè)類的繼承關(guān)系,每個(gè)類都包括對(duì)幾個(gè)函數(shù)的定義和聲明。這里簡(jiǎn)單介紹一下f1()函數(shù),讀者可以通過(guò)表2的內(nèi)容來(lái)理解其他函數(shù)。 f1在A類中是虛函數(shù),而且有定義,在C類中有定義,所以當(dāng)D類繼承C類時(shí),D類中就不能再有定義(“√”表示可以定義,“*”表示不推薦再繼續(xù)定義)。例外是f4,雖然它在A類中有定義,但是因?yàn)樗羌兲摵瘮?shù),所以它的定義會(huì)被忽略。

這個(gè)規(guī)則說(shuō)明,如果在一個(gè)繼承路徑上有兩個(gè)函數(shù)定義,在調(diào)用函數(shù)時(shí),有可能按照繼承的優(yōu)先度調(diào)用函數(shù)。這樣就會(huì)導(dǎo)致函數(shù)調(diào)用的混亂,可能會(huì)調(diào)不到程序員希望的函數(shù)。這是在實(shí)現(xiàn)多態(tài)時(shí)需要特別注意的地方。關(guān)于繼承路徑上的函數(shù)定義,C++并沒(méi)有明確限制。

從上面的例程可以看出,如果沒(méi)有這樣的限制,就會(huì)產(chǎn)生一些混亂,雖然程序能夠正常運(yùn)行,但是不一定能夠按照程序員所設(shè)計(jì)的方式運(yùn)行。這樣的運(yùn)行方式會(huì)出現(xiàn)很多漏洞,所以MISRA C++強(qiáng)制規(guī)定在每一個(gè)繼承路徑上,虛函數(shù)只能有一個(gè)定義。

規(guī)則10-3-2(強(qiáng)制):每一個(gè)重載的虛函數(shù)應(yīng)該用關(guān)鍵字virtual來(lái)聲明。

這樣做不需要檢查基類,就可以確定函數(shù)是否為虛函數(shù)。MISRA C++推出這樣的規(guī)則是為了使C++程序更加完善。

規(guī)則10-3-3(強(qiáng)制):只有被聲明為純虛函數(shù)的虛函數(shù),才能被純虛函數(shù)重載。

foo函數(shù)在A類中定義為純虛函數(shù),在B類中被重載為普通虛函數(shù)。而C類使用純虛函數(shù)重載foo函數(shù)。這樣做是不行的。

B類中foo函數(shù)重載A類的foo函數(shù)時(shí),是用有定義的虛函數(shù)重載純虛函數(shù),這樣做是可以的。

C類中的foo函數(shù)重載B類的foo函數(shù)時(shí),是用純虛函數(shù)重載一個(gè)非純虛函數(shù),這樣是不行的。在C類中,foo被定義為純虛函數(shù),在C類的對(duì)象調(diào)用foo 函數(shù)時(shí)無(wú)法調(diào)用到B類中的定義。這樣的重載導(dǎo)致B類中對(duì)foo函數(shù)的定義丟失。

所以MISRA C++不允許使用純虛函數(shù)重載非純虛函數(shù),這樣做的目的也是為了使C++程序更加安全。

3 小結(jié)

正確并完備地實(shí)現(xiàn)C++的多態(tài)性,能夠充分發(fā)揮C++的優(yōu)勢(shì),并且提高程序的可讀性和可維護(hù)性。如果使用不當(dāng),會(huì)導(dǎo)致一些想象不到的程序漏洞。MISRA C++針對(duì)使用多態(tài)性可能產(chǎn)生的一些漏洞,提出了規(guī)避的方法與建議。本文列出了其中幾條比較關(guān)鍵和實(shí)用的規(guī)則。關(guān)于多態(tài)性的其他規(guī)則,讀者可以查看。 MISRA C++(2008),以避免不正確使用多態(tài)性所導(dǎo)致的一些程序漏洞。

責(zé)任編輯:gt

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C++
    C++
    +關(guān)注

    關(guān)注

    21

    文章

    2090

    瀏覽量

    73404
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1607

    瀏覽量

    48977
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何完備地實(shí)現(xiàn)C++多態(tài)性

    如何完備地實(shí)現(xiàn)C++多態(tài)性?虛函數(shù)怎么使用?
    發(fā)表于 04-28 06:44

    利用P2P的網(wǎng)絡(luò)特性構(gòu)造多態(tài)性密碼

    為了解決沒(méi)有第三方認(rèn)證的情況下,P2P 網(wǎng)絡(luò)通信過(guò)程中對(duì)等點(diǎn)的授權(quán)問(wèn)題,本文基于P2P 網(wǎng)絡(luò)中對(duì)等點(diǎn)的信任度管理,提出了利用P2P 網(wǎng)絡(luò)結(jié)構(gòu)的特點(diǎn)來(lái)構(gòu)造一個(gè)多態(tài)性密碼的新方法
    發(fā)表于 06-20 09:35 ?8次下載

    基于Java多態(tài)性的應(yīng)用程序設(shè)計(jì)

    Java 中的多態(tài)體現(xiàn)在類的繼承和實(shí)現(xiàn)接口等方面。通過(guò)對(duì)與多態(tài)有關(guān)的概念進(jìn)行歸納比較,從繼承和接口兩方面對(duì)多態(tài)的正確實(shí)現(xiàn)進(jìn)行分析,結(jié)合實(shí)例說(shuō)明多態(tài)性在程序設(shè)計(jì)中的
    發(fā)表于 09-09 08:51 ?24次下載

    什么是方法的重載(多態(tài)性)?

    什么是方法的重載(多態(tài)性)? 在同一個(gè)類中至少有兩個(gè)方法用同一個(gè)名字,但有不同的參數(shù)。
    發(fā)表于 04-28 14:28 ?1263次閱讀
    什么是<b class='flag-5'>方法</b>的重載(<b class='flag-5'>多態(tài)性</b>)?

    C++的動(dòng)態(tài)多態(tài)和靜態(tài)多態(tài)

    多態(tài)C++ 中面向?qū)ο蠹夹g(shù)的核心機(jī)制之一包含靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)它們之間有一定的相似但是應(yīng)用范圍不同該文論述了這種相似
    發(fā)表于 06-29 15:41 ?41次下載
    <b class='flag-5'>C++</b>的動(dòng)態(tài)<b class='flag-5'>多態(tài)</b>和靜態(tài)<b class='flag-5'>多態(tài)</b>

    數(shù)據(jù)的共享和保護(hù)以及多態(tài)性_實(shí)驗(yàn)4

    c++面向?qū)ο笳n程實(shí)驗(yàn)指導(dǎo)書題目_數(shù)據(jù)的共享和保護(hù)以及多態(tài)性
    發(fā)表于 01-14 16:25 ?0次下載

    java多態(tài)性的實(shí)現(xiàn)

    Java中多態(tài)性的實(shí)現(xiàn) 什么是多態(tài) 面向?qū)ο蟮娜筇匦裕悍庋b、繼承、多態(tài)。從一定角度來(lái)看,封裝和繼承幾乎都是為多態(tài)而準(zhǔn)備的。這是我們最后一個(gè)概念,也是最重要的知識(shí)點(diǎn)。
    發(fā)表于 09-27 10:36 ?9次下載

    探討C++多態(tài)性技術(shù)的局限性及解決的辦法

    多態(tài)性是指發(fā)出同樣的消息被不同類型的對(duì)象接收時(shí)有可能導(dǎo)致完全不同的行為。
    的頭像 發(fā)表于 01-08 11:06 ?3597次閱讀

    C++課程資料詳細(xì)資料合集包括了:面向?qū)ο蟪绦蛟O(shè)計(jì)與C++,算法,函數(shù)等

    ,循環(huán),多態(tài)性,數(shù)組,模板,習(xí)題,STL編程,預(yù)處理,指針,結(jié)構(gòu)體,位運(yùn)算,文件,常見錯(cuò)誤,c++模板使用疑問(wèn)等
    發(fā)表于 07-09 08:00 ?18次下載
    <b class='flag-5'>C++</b>課程資料詳細(xì)資料合集包括了:面向?qū)ο蟪绦蛟O(shè)計(jì)與<b class='flag-5'>C++</b>,算法,函數(shù)等

    C++程序設(shè)計(jì)教程之多態(tài)性與虛函數(shù)的詳細(xì)資料說(shuō)明

    本文檔詳細(xì)介紹的是C++程序設(shè)計(jì)教程之多態(tài)性與虛函數(shù)的詳細(xì)資料說(shuō)明主要資料包括了:1 多態(tài)性的概念,2 一個(gè)典型的例子,3 虛函數(shù),4 純虛函數(shù)與抽象類
    發(fā)表于 03-14 16:39 ?5次下載
    <b class='flag-5'>C++</b>程序設(shè)計(jì)教程之<b class='flag-5'>多態(tài)性</b>與虛函數(shù)的詳細(xì)資料說(shuō)明

    C++中如何用虛函數(shù)實(shí)現(xiàn)多態(tài)

    01 — C++虛函數(shù)探索 C++是一門面向?qū)ο笳Z(yǔ)言,在C++里運(yùn)行時(shí)多態(tài)是由虛函數(shù)和純虛函數(shù)實(shí)現(xiàn)的,現(xiàn)在我們看下在C++中如何用虛函數(shù)實(shí)現(xiàn)
    的頭像 發(fā)表于 09-29 14:18 ?1641次閱讀

    多態(tài)性實(shí)現(xiàn)原理及其在面向?qū)ο缶幊讨械膽?yīng)用

    在面向?qū)ο蟮木幊讨校?b class='flag-5'>多態(tài)性是一個(gè)非常重要的概念。
    的頭像 發(fā)表于 06-08 14:19 ?557次閱讀

    您需要了解的有關(guān)下一個(gè)MISRA?標(biāo)準(zhǔn)的信息:MISRA C++ 2023?簡(jiǎn)介

    軟件可靠協(xié)會(huì)(MISRA)開發(fā)的一套CC++編碼標(biāo)準(zhǔn),不僅是汽車行業(yè)的最佳標(biāo)準(zhǔn)之一,也是任何使用嵌入式系統(tǒng)的行業(yè)的最佳標(biāo)準(zhǔn)之一。
    的頭像 發(fā)表于 08-25 18:06 ?1233次閱讀
    您需要了解的有關(guān)下一個(gè)<b class='flag-5'>MISRA</b>?標(biāo)準(zhǔn)的信息:<b class='flag-5'>MISRA</b> <b class='flag-5'>C++</b> 2023?簡(jiǎn)介

    使用 MISRA C++:2023? 避免基于范圍的 for 循環(huán)中的錯(cuò)誤

    在前兩篇博客中,我們?向您介紹了新的 MISRA C++ 標(biāo)準(zhǔn)?和?C++ 的歷史?。在這篇博客中,我們將仔細(xì)研究以 C++ 中?for?循環(huán)為中心的特定規(guī)則。
    的頭像 發(fā)表于 03-28 13:53 ?657次閱讀
    使用 <b class='flag-5'>MISRA</b> <b class='flag-5'>C++</b>:2023? 避免基于范圍的 for 循環(huán)中的錯(cuò)誤

    embOS的MISRA-C:2012一致

    MISRA C是汽車工業(yè)軟件可靠協(xié)會(huì)(MISRA)開發(fā)的一套針對(duì)C編程語(yǔ)言的軟件開發(fā)指南,目的
    的頭像 發(fā)表于 08-20 11:35 ?343次閱讀