版上的各位大家好,我是一個C++新手,來問一些觀念!
https://ideone.com/e0fFAE
這是我的練習內容,我目前遇到一些困難!
在程式內我有註解
CHuman ,CEmployee解構式如果要delete[] 就會讓資料消失了!可是觀念上new 跟delete要成對才對,還是我應該怎麼正確地去delete呢
CEmployees 建構式裡的new是不是應該要一開始就寫上,我理解應該要這樣寫第一筆資料才能順利Add進去,但是指導者跟我說我這樣new了兩次(我解釋說我有在函式內delete mEmployees 但是他說我觀念有誤) 請問這邊我有出現甚麼問題嗎,拜託各位大大!
如果不是規定一定要用 array 的話
建議可以考慮看看
用 Vector
根據該網友的說法
C/C++ array’s size do not change dynamically
基本上無法達到「動態」陣列的目的
頂多就是 delete then define 的做法
就算做出來了
也是很不仗義的做法
(為了加/減一個 element,要整個陣列複製來複製去的)
只是比較粗略的看一下
這些改好還有其他問題再討論
NewEmployees[index] = mEmployees[count];
這邊是不是要寫 NewEmployees[index] = mEmployees[index];
另外這邊的 =
(assign) 要另外處理
否則裡面的 CEmployee.mId 及 CHuman.mName 只會複製指標
但是該指標所指的位址卻因為64行的 delete 連帶被釋放了
cin>>name;
這邊 name 的資料型態是 char*
,其所指的空間只有1個 char
所以這邊應該是會超出所宣告的記憶體空間
這會造成程式錯誤或崩潰
cin>>id;
同 92 行問題
需要動態空間的話大概可以這樣
//====資料====
SomeType(某資料型態) *p;
int capacity; //容量
int index; //寫入到哪邊,0<=index<capacity
//===建構===
p=new SomeType(基礎長度)
capacity=基礎長度
index=0
//===寫入===
if(index+寫入的長度>=capacity) {
擴充容量(並更新capacity)
}
寫入資料(並更新 index)
PS. 擴充容量的方式有很多種,常見的方式是每次容量乘以2
最大的問題在CHuman的new/delete要能成對,
如果沒調用過SetName就沒有new過,
而解構固定delete的話當然就會出錯了
所以可以這樣調整
建構時先給予初值為空
mName = NULL;
解構時,判斷不為空才delete
if (mName) delete[] mName;
同樣的,所謂new了兩次的問題,可在SetName加以預防,
在new之前先判斷如果不為空要先delete,
這跟剛剛解構裏所加的程式碼相同,
if (mName) delete[] mName;
弄懂前述大原則後, 就能寫出所有正確的邏輯方式,
指導員就不會說你觀念有誤了, 至於其他小問題自行除錯吧!
首先想要正確新增CEmployee
下面的程式碼會有問題
NewEmployees[index] = mEmployees[count];
這樣只會把mEmployees[count]的元素複製到每個NewEmployees[index]中
正確程式碼應該為
NewEmployees[index] = mEmployees[index];
程式會當掉可以用cout看出原因
cout << "debug 2\n";
delete[] mName;
...
cout << "debug 1\n";
delete[] mEmployees;
加上除錯訊息後delete的順序
debug 1
debug 2
debug 2
"debug 2"跑了兩次,可見delete[] mEmployees;也會跑CHuman的解構子亦即delete[] mName;
那new與delete還會一定要成對嗎?
mEmployees = new CEmployee[count+1];//請問這行可以省略嗎
如果不在建構的時候就設置空間 是不是就不能成功Add第一筆
這可以寫程式碼驗證
例如寫一個List方法確認有沒有新增CEmployee成功,
void List() {
CEmployee * e = NULL;
for (int i = 0; i < count; ++i)
{
e = &mEmployees[i];
cout << "ID: " << (*e).GetId() << "\n"
<< "姓名: " << (*e).GetName() << "\n"
<< "年齡: " << (*e).GetAge() << "\n";
}
}
新增成功後,呼叫List去看列出來的結果
...
Employees.Add(Employee);
cout<<"Finish !\n";
Employees.List();
...
可以先思考什麼型態較適合描述員工登錄/查詢系統
若員工人數有限制,例如100人,那CEmployee[100]可以搞定
class CEmployees {
private:
CEmployee mEmployees[100];
int count;
...
}
若員工人數無限制,那vector<CEmployee>比較適合
class CEmployees {
private:
vector<CEmployee> mEmployees;
int count;
...
}
希望有幫助到你