原代碼問題
class CStudent {
char *name;
int age;
public:
CStudent(char *n, int a) : age(a) {
int nLen = strlen(n);
name = new char[nLen+1];
strcpy(name, n);
name[nLen] = '\0'; // 多餘,strcpy 已包含
}
~CStudent() { delete[] name; }
// 缺少拷貝構造函數、賦值運算符 → 淺拷貝導致雙重釋放
};
完整正確實現 (Rule of Three)
class CStudent {
char *name;
int age;
public:
// 構造
CStudent(const char *n = "", int a = 0) : age(a) {
name = new char[strlen(n) + 1];
strcpy(name, n);
}
// 拷貝構造
CStudent(const CStudent &other) : age(other.age) {
name = new char[strlen(other.name) + 1];
strcpy(name, other.name);
}
// 賦值運算符
CStudent& operator=(const CStudent &other) {
if (this != &other) {
delete[] name;
age = other.age;
name = new char[strlen(other.name) + 1];
strcpy(name, other.name);
}
return *this;
}
// 移動構造 (C++11)
CStudent(CStudent &&other) noexcept : name(other.name), age(other.age) {
other.name = nullptr;
}
// 移動賦值
CStudent& operator=(CStudent &&other) noexcept {
if (this != &other) {
delete[] name;
name = other.name;
age = other.age;
other.name = nullptr;
}
return *this;
}
~CStudent() { delete[] name; }
// Getter/Setter
const char* getName() const { return name; }
void setName(const char *n) {
delete[] name;
name = new char[strlen(n) + 1];
strcpy(name, n);
}
};
CTeacher 關聯 CStudent 正確設計
class CTeacher {
char *name;
int age;
CStudent stu; // 直接包含對象(值語義),而非指針
public:
CTeacher(const char *tn, int ta) : age(ta) {
name = new char[strlen(tn) + 1];
strcpy(name, tn);
}
// 同樣需要 Rule of Three/Five
void SetStuAge(int a) { stu.setAge(a); } // 假設 CStudent 有 setAge
// ...
};
關鍵點
- 管理動態內存的類**必須**實現拷貝構造、賦值運算符、析構函數(C++11 加移動語義)。
- 優先使用
std::string 替代 char*,自動管理內存,避免手動錯誤。
- 成員對象直接包含(值語義)而非指針,簡化所有權管理。
- 構造函數參數用
const char*,避免修改字面量導致崩潰。
現代 C++ 建議
#include <string>
class Student {
std::string name;
int age;
public:
Student(const std::string& n, int a) : name(n), age(a) {}
// 無需手寫拷貝/移動/析構,編譯器生成正確
};