您好,登錄后才能下訂單哦!
本篇內容介紹了“C++中新手容易犯的編程錯誤有哪些”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
對于C++類,一些關鍵字只要寫在.h中就好,cpp中就不用再加上了,比如virtual、static等關鍵字,如果再cpp中多寫,編譯器會報錯。比如如下的虛接口與靜態成員變量的定義,只要在頭文件中聲明就可以了。
class shape { virtual Draw(); //... static int nLevel; }
帶有參數默認值的函數,默認值是加在函數聲明處的,函數實現處的參數是不需要帶上的。為了方便查看代碼,在函數實現處的參數中,將默認值注釋起來。正確的做法是,頭文件中有默認值:
BOOL CreateConf( const CString& strConfName, const BOOL bAudio = FALSE );
在函數實現處的參數中不用添加默認值:
BOOL CreateConf( const CString& strConfName, const BOOL bAudio/* = FALSE*/ ); { // ...... }
在類的結尾處忘記添加分號,編譯會報錯,新人們有可能找了半天也沒找出引起編譯錯誤的原因。其實很簡單,在類的結尾處忘記添加分號了。
class Shape { // ... };
在添加類的函數時,只在類的頭文件中添加了函數聲明,但在cpp中卻沒有添加函數的實現。如果其他地方調用到該函數,在編譯鏈接的時候會報 unresolved external symbol錯誤。因為沒有實現,所有沒有供鏈接使用的obj文件。
在添加C++類時,我們一般會添加.h頭文件和一個.cpp源文件。結果忘記把.cpp文件添加到工程中了,即沒有參與編譯,沒有生成供鏈接使用的obj文件。如果有代碼調用到該C++類的接口,則在編譯鏈接的時候會報 unresolved external symbol錯誤,即鏈接不到該C++類對應的接口。
在函數中返回了一個局部變量的地址或者引用,而這個局部變量在函數結束時其生命周期就結束了,內存就被釋放了。當外部訪問到該變量的內存,會觸發內存訪問違例的異常,因為該變量的內存已經釋放了。比如如下的錯誤代碼:
char* GetResult() { char chResult[100] = { 0 }; // ...... return chResult; }
代碼中本來要借助于C++多態的虛函數調用,調用子類實現的接口,結果忘記在父類中將對應的接口聲明為virtual,導致沒有調用到子類實現的函數。一定要記住,要實現多態下的函數調用,父類的相關接口必須聲明為virtual。
class Shape() { // ... virtual void Draw(); // ... }
有時我們需要調用一個接口去獲取某些數據,接口中將數據拷貝到傳入的參數對應的內存中,此時設計參數時會傳入指針或引用。我們在調用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)); }
比如新人用VS-MFC庫編寫一個測試用的工具軟件,結果在發布release版本程序時,沒有將程序依賴的C運行時庫帶上,導致該工具軟件在某些電腦中啟動報錯,提示找不到C運行時庫:
因為程序中依賴了動態版本的運行時庫和MFC庫,在發布程序時要將這些庫帶上。有些系統中沒有這些庫,程序啟動時就會報找不到庫,就會啟動失敗。
本來應該要進行深拷貝的,卻使用了淺拷貝(直接賦值),導致另個不同生命周期的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;//得分點:返回本對象的引用 }
“C++中新手容易犯的編程錯誤有哪些”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。