1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        C++編程新手容易犯的 10 種編程錯誤

        共 3563字,需瀏覽 8分鐘

         ·

        2022-04-25 06:52


        來源:網絡素材

        整理:李肖遙


        1、有些關鍵字在 cpp 文件中多寫了

        對于 C++ 類,一些關鍵字只要寫在 .h 中就好,cpp 中就不用再加上了,比如 virtual、static 等關鍵字,如果在 cpp 中多寫,編譯器會報錯。比如如下的虛接口與靜態(tài)成員變量的定義,只要在頭文件中聲明就可以了。

        class?shape
        {
        ????virtual?Draw();
        ????//...
        ????static?int?nLevel;
        }

        2、函數參數的默認值寫到函數實現中了

        帶有參數默認值的函數,默認值是加在函數聲明處的,函數實現處的參數是不需要帶上的。為了方便查看代碼,在函數實現處的參數中,將默認值注釋起來。正確的做法是,頭文件中有默認值:

        BOOL?CreateConf(?const?CString&?strConfName,?const?BOOL?bAudio?=?FALSE?);
        在函數實現處的參數中不用添加默認值:
        BOOL?CreateConf(?const?CString&?strConfName,?const?BOOL?bAudio/*?=?FALSE*/?);
        {
        ????//?......
        }

        3、在編寫類的時候,在類的結尾處忘記添加 ";" 分號了

        在類的結尾處忘記添加分號,編譯會報錯,新人們有可能找了半天也沒找出引起編譯錯誤的原因。其實很簡單,在類的結尾處忘記添加分號了。

        class?Shape
        {
        ????//?...
        };

        4、只添加了函數聲明,沒有函數實現

        在添加類的函數時,只在類的頭文件中添加了函數聲明,但在 cpp 中卻沒有添加函數的實現。如果其他地方調用到該函數,在編譯鏈接的時候會報unresolved external symbol錯誤。因為沒有實現,所有沒有供鏈接使用的 obj 文件。

        5、cpp 文件忘記添加到工程中,導致沒有生成供鏈接使用的 obj 文件

        在添加 C++ 類時,我們一般會添加 .h 頭文件和一個 .cpp 源文件。結果忘記把 .cpp 文件添加到工程中了,即沒有參與編譯,沒有生成供鏈接使用的 obj 文件。如果有代碼調用到該 C++ 類的接口,則在編譯鏈接的時候會報unresolved external symbol錯誤,即鏈接不到該 C++ 類對應的接口。

        6、函數中返回了一個局部變量的地址或者引用

        在函數中返回了一個局部變量的地址或者引用,而這個局部變量在函數結束時其生命周期就結束了,內存就被釋放了。當外部訪問到該變量的內存,會觸發(fā)內存訪問違例的異常,因為該變量的內存已經釋放了。比如如下的錯誤代碼:

        char*?GetResult()
        {
        ????char?chResult[100]?=?{?0?};

        ????//?......

        ????return?chResult;
        }

        7、忘記將父類中的接口聲明 virtual 函數,導致多態(tài)沒有生效

        代碼中本來要借助于 C++ 多態(tài)的虛函數調用,調用子類實現的接口,結果忘記在父類中將對應的接口聲明為 virtual,導致沒有調用到子類實現的函數。一定要記住,要實現多態(tài)下的函數調用,父類的相關接口必須聲明為 virtual。

        class?Shape()
        {
        ????//?...

        ????virtual?void?Draw();

        ????//?...
        }

        8、該使用雙指針的地方,卻使用了單指針

        有時我們需要調用一個接口去獲取某些數據,接口中將數據拷貝到傳入的參數對應的內存中,此時設計參數時會傳入指針或引用。我們在調用GetData 之前定義了結構體指針p,并 new 出了對應的結構體對象內存,應該在定義 GetData 接口時應該使用雙指針(指針的指針)的,結果錯寫成了單指針。

        有問題的代碼如下:

        struct?CodecInfo?????//?編碼信息
        {
        ??? int nFrameRate;

        ????//?...
        }


        CodecInfo*?pInfo?=?new?CodecInfo;

        GetAudioCodecPtr()->GetCodecInfo(pInfo);???//?調用AudioCodec::GetCodecInfo獲取編碼信息


        AudioCodec::GetCodecInfo(?CodecInfo*?pInfo)??//?此處的參數不應該使用單指針
        {
        ????memcpy(pInfo,?m_codecInfo,?sizeof(CodecInfo));
        }

        上面中的AudioCodec::GetCodecInfo接口的參數不應該為單指針,應該用雙指針,修改后的代碼應該如下:

        AudioCodec::GetCodecInfo(?CodecInfo**?pInfo)??//?此處的參數類型使用雙指針
        {
        ????memcpy(*pInfo,?m_codecInfo,?sizeof(CodecInfo));
        }

        9、發(fā)布 exe 程序時,忘記將 exe 依賴的 C 運行時庫和 MFC 庫帶上

        比如新人用 VS-MFC 庫編寫一個測試用的工具軟件,結果在發(fā)布 release 版本程序時,沒有將程序依賴的 C 運行時庫帶上,導致該工具軟件在某些電腦中啟動報錯,提示找不到 C 運行時庫:

        因為程序中依賴了動態(tài)版本的運行時庫和 MFC 庫,在發(fā)布程序時要將這些庫帶上。有些系統(tǒng)中沒有這些庫,程序啟動時就會報找不到庫,就會啟動失敗。

        10、應該使用深拷貝,卻使用了淺拷貝

        本來應該要進行深拷貝的,卻使用了淺拷貝(直接賦值),導致另個不同生命周期的 C++ 對象指向了同一塊內存,一個對象將內存釋放后,另一個對象再用到這塊內存,就造成了內存訪問違例,產生異常。

        有個經典的 C++ 筆試題,讓我們實現 String 類的相關函數,其主要目的就是用來考察對深拷貝與淺拷貝的理解的。題目中給出 String類的聲明:

        class?String{
        public:
        ????String();
        ????String(const?String?&?str);
        ????String(const?char*?str);
        ????String&?operator=(String?str);
        ????char*?c_str()?const;
        ????~String();
        ????int?size()?const;
        private:
        ????char*?data;
        };

        讓寫出上述幾個函數的內部實現。這些函數的實現代碼如下:

        //普通構造函數??
        String::String(const?char?*str)
        {
        ??if?(str?==?NULL)
        ??{
        ??? m_data = new char[1];//?得分點:對空字符串自動申請存放結束標志'\0'的,加分點:對m_data加NULL判斷??
        ????*m_data?=?'\0';
        ??}
        ??else
        ??{
        ????int?length?=?strlen(str);
        ????m_data?=?new?char[length?+?1];//?若能加?NULL?判斷則更好
        ????strcpy(m_data,?str);
        ??}
        }
        ?
        ?
        //?String的析構函數??
        String::~String(void)
        {
        ??delete[]?m_data;?//?或delete?m_data;??
        }
        ?
        ?
        //拷貝構造函數??
        String::String(const String &other)//?得分點:輸入參數為const型??
        {?????
        ??int?length?=?strlen(other.m_data);
        ??m_data?=?new?char[length?+?1];//?若能加?NULL?判斷則更好??
        ??strcpy(m_data,?other.m_data);
        }
        ?
        ?
        //賦值函數??
        String & String::operator =?(const String &other)?//?得分點:輸入參數為const型??
        {
        ??if?(this ==?&other)//得分點:檢查自賦值??
        ????return?*this;?
        ??if?(m_data)
        ????? delete[] m_data;//得分點:釋放原有的內存資源??
        ??int?length?=?strlen(other.m_data);
        ? m_data = new char[length + 1];//加分點:對m_data加NULL判斷??
        ??strcpy(m_data,?other.m_data);
        ??return?*this;//得分點:返回本對象的引用????
        }

        ???????????????? ?END ????????????????

        瀏覽 15
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美一级视频 | 啊轻点灬太粗嗯太深了视频在线观看 | 熟女乱码 | aaa日韩| 亚洲AU秘 一区二区三区九色下 | 超碰av导航 | 国产女主播在线 | 国产成人无码区亚洲A片356p | 欧美国产日韩一区二区 | 一区在线观看视频 |