class CEleStudent
{
private:
int m_nYears;
TCHAR *m_tcName;
public:
CEleStudent() {m_nYears = 7; m_tcName = _T("NoName");};
CEleStudent(int n, const TCHAR *tc)
{
m_nYears = n;
m_tcName = (TCHAR*)malloc(sizeof(TCHAR) * (lstrlen(tc) + 1));
_tcscpy(m_tcName , tc);
};
CEleStudent(int n) {m_nYears = n; m_tcName = NULL;};
};
在我們沒有明確定義 operator= 的時後,若我做撰寫以下程式碼會發生一些問題
int main()
{
CEleStudent std;
std = 9;
cout << std.m_tcName; return TRUE;
}
在宣告std時因為沒有指定任何建構式,所以經過預設無參數的建構式後產生了年紀7歲的物件,但下一行 std = 9 就有問題了,編譯器會將此行代碼拆解成它自己看得懂的方式,
CEleStudent tmp(10); // m_nYears 為 10,m_tcName 為 NULL
std = tmp; // 將 Years 由 7 改為 10,NoName 改為 NULL 空指標
這種轉換過程就稱為隱轉型,在有適當參數的建構式下編譯器會自行呼叫,就像 int n = 9; double dbl; dbl = n; 這是最常見的隱轉型。
在 m_tcName 為空指標的狀況下,第三行的 cout 就有可能在執行期間出問題嘍,加上原本被 malloc 分派出來的記憶體沒有經過 free() 的動作也是一個問題,畢免這種情況的發生可以使用 explicit 關鍵字,就像它的名稱一樣,該類別的建構式無法被調用來做隱式轉型的動作,
修改如下
class CEleStudent
{
...
explicit CEleStudent(int n) {m_nYears = n; m_tcName = NULL;};
};
如此當有其他人使用你的類別時,只要出現 obj = 整數這種指令,編譯期即會收到一項無法轉型的 compil error 的訊息,必須明確的指明
CEleStudent std;
std = (std)9;
或
std = std(9);
這可以確實的將一些錯誤擋在編譯時期,比發生在執行期好多了,但需注意的是 explicit 關鍵字用於多參數的建構式是會產生語法錯誤的,所以 CEleStudent(int n, const TCHAR *tc) 就沒辦法加上 explicit。
沒有留言:
張貼留言