1、有些關鍵字在 cpp 文件中多寫了
對于 C++ 類,一些關鍵字只要寫在 .h 中就好,cpp 中就不用再加上了,比如 virtual、static 等關鍵字,如果在 cpp 中多寫,編譯器會報錯。
比如如下的虛接口與靜態成員變量的定義,只要在頭文件中聲明就可以了。
classshape
{
virtualDraw();
//...
staticintnLevel;
}
2、函數參數的默認值寫到函數實現中了
帶有參數默認值的函數,默認值是加在函數聲明處的,函數實現處的參數是不需要帶上的。
為了方便查看代碼,在函數實現處的參數中,將默認值注釋起來。正確的做法是,頭文件中有默認值:
BOOLCreateConf(constCString&strConfName,constBOOLbAudio=FALSE);
在函數實現處的參數中不用添加默認值:
BOOLCreateConf(constCString&strConfName,constBOOLbAudio/*=FALSE*/);
{
//......
}
3、在編寫類的時候,在類的結尾處忘記添加 ";" 分號了
在類的結尾處忘記添加分號,編譯會報錯,新人們有可能找了半天也沒找出引起編譯錯誤的原因。
其實很簡單,在類的結尾處忘記添加分號了。
classShape
{
//...
};
4、只添加了函數聲明,沒有函數實現
在添加類的函數時,只在類的頭文件中添加了函數聲明,但在 cpp 中卻沒有添加函數的實現。
如果其他地方調用到該函數,在編譯鏈接的時候會報unresolved external symbol錯誤。因為沒有實現,所有沒有供鏈接使用的 obj 文件。
5、cpp 文件忘記添加到工程中,導致沒有生成供鏈接使用的 obj 文件
在添加 C++ 類時,我們一般會添加 .h 頭文件和一個 .cpp 源文件。結果忘記把 .cpp 文件添加到工程中了,即沒有參與編譯,沒有生成供鏈接使用的 obj 文件。
如果有代碼調用到該 C++ 類的接口,則在編譯鏈接的時候會報unresolved external symbol錯誤,即鏈接不到該 C++ 類對應的接口。
6、函數中返回了一個局部變量的地址或者引用
在函數中返回了一個局部變量的地址或者引用,而這個局部變量在函數結束時其生命周期就結束了,內存就被釋放了。
當外部訪問到該變量的內存,會觸發內存訪問違例的異常,因為該變量的內存已經釋放了。比如如下的錯誤代碼:
char*GetResult()
{
charchResult[100]={0};
//......
returnchResult;
}
7、忘記將父類中的接口聲明 virtual 函數,導致多態沒有生效
代碼中本來要借助于 C++ 多態的虛函數調用,調用子類實現的接口,結果忘記在父類中將對應的接口聲明為 virtual,導致沒有調用到子類實現的函數。
一定要記住,要實現多態下的函數調用,父類的相關接口必須聲明為 virtual。
classShape()
{
//...
virtualvoidDraw();
//...
}
8、該使用雙指針的地方,卻使用了單指針
有時我們需要調用一個接口去獲取某些數據,接口中將數據拷貝到傳入的參數對應的內存中,此時設計參數時會傳入指針或引用。
我們在調用GetData 之前定義了結構體指針p,并 new 出了對應的結構體對象內存,應該在定義 GetData 接口時應該使用雙指針(指針的指針)的,結果錯寫成了單指針。
有問題的代碼如下:
structCodecInfo//編碼信息
{
int nFrameRate;
//...
}
CodecInfo*pInfo=newCodecInfo;
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、發布 exe 程序時,忘記將 exe 依賴的 C 運行時庫和 MFC 庫帶上
比如新人用 VS-MFC 庫編寫一個測試用的工具軟件,結果在發布 release 版本程序時,沒有將程序依賴的 C 運行時庫帶上,導致該工具軟件在某些電腦中啟動報錯,提示找不到 C 運行時庫:
因為程序中依賴了動態版本的運行時庫和 MFC 庫,在發布程序時要將這些庫帶上。有些系統中沒有這些庫,程序啟動時就會報找不到庫,就會啟動失敗。
10、應該使用深拷貝,卻使用了淺拷貝
本來應該要進行深拷貝的,卻使用了淺拷貝(直接賦值),導致另個不同生命周期的 C++ 對象指向了同一塊內存,一個對象將內存釋放后,另一個對象再用到這塊內存,就造成了內存訪問違例,產生異常。
有個經典的 C++ 筆試題,讓我們實現 String 類的相關函數,其主要目的就是用來考察對深拷貝與淺拷貝的理解的。題目中給出String類的聲明:
classString{
public:
String();
String(constString&str);
String(constchar*str);
String&operator=(Stringstr);
char*c_str()const;
~String();
intsize()const;
private:
char*data;
};
讓寫出上述幾個函數的內部實現。這些函數的實現代碼如下:
//普通構造函數
String::String(constchar*str)
{
if(str==NULL)
{
m_data = new char[1];//得分點:對空字符串自動申請存放結束標志'?'的,加分點:對m_data加NULL判斷
*m_data='?';
}
else
{
intlength=strlen(str);
m_data=newchar[length+1];//若能加NULL判斷則更好
strcpy(m_data,str);
}
}
//String的析構函數
String::~String(void)
{
delete[]m_data;//或deletem_data;
}
//拷貝構造函數
String::String(const String &other)//得分點:輸入參數為const型
{
intlength=strlen(other.m_data);
m_data=newchar[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;//得分點:釋放原有的內存資源
intlength=strlen(other.m_data);
m_data = new char[length + 1];//加分點:對m_data加NULL判斷
strcpy(m_data,other.m_data);
return*this;//得分點:返回本對象的引用
}
審核編輯:劉清
-
嵌入式
+關注
關注
5198文章
20442瀏覽量
333979 -
變量
+關注
關注
0文章
616瀏覽量
29505 -
C++語言
+關注
關注
0文章
147瀏覽量
7682
原文標題:嵌入式C++中常見的錯誤形式
文章出處:【微信號:嵌入式開發愛好者,微信公眾號:嵌入式開發愛好者】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
嵌入式C開發中段錯誤的3種調試方法
嵌入式實時程序設計中C/C++代碼的優化
嵌入式C++編程
簡單總結一下嵌入式C++中常見的錯誤形式
評論