1. 類需要建構函式嗎?
2. 資料是否需要保持私人的?
方案一
public:
int length;
方案二
public:
const int& length;//在建構函式中length = true_length;這樣由於是const變數,只能讀,不能修改。
private:
int true_length;
方案三
public:
int length() const;//
3. 是否需要一個無參的建構函式?
如果沒有無參的建構函式,那麼
Point p;
Point pa[100];
這樣的定義都是錯誤的。
4. 是不是每個建構函式初始化所有的資料成員?
建構函式的用途就是用一種明確定義的狀態來設定對象,而這個對象是由對象的資料成員反映的。
因此每個建構函式都要負責為所有資料成員設定明確定義的值。(特殊的例外)
5. 是否需要解構函式?
如果有記憶體是在類中new出來,但一直也沒有釋放的,需要在解構函式中釋放掉。
6. 是否需要虛解構函式?
如果一個基類B被派生了一個子類D,無論B是否有虛函數
B* d = new D();
delete d; //B都需要虛解構函式,否則這裡會調用錯誤的解構函式
7. 是否需要複製建構函式?
因為data的記憶體是另外動態分配的。所以應該需要解構函式來釋放data空間
class String{
public:
String();
String(const char* s);
private
char* data
}
因為data的記憶體是另外動態分配的。所以應該需要解構函式來釋放data的空間。
同樣也需要複製建構函式,因為如果沒有的話,如果複製對象
String b = a
就是僅複製data的地址,b.data和a.data指象同一個記憶體,在兩個對象銷毀時,這個記憶體會被釋放兩次。
如果不希望使用者能夠複製類的對象,就聲明複製建構函式(可能還有賦值操作符)為私人的
class Thing{
private
Thing(const Thing&);
Thing& operator=(const Thing&);
}
8. 需要一個賦值操作符嗎?
是否需要的理由和複製建構函式是一樣的。
Thing& operator=(const Thing&);
由return *this;結束以保證與內建的複製操作符一致。
寫這個函數的時候還要注意賦值給自身的情況
String& String::operator=(const String& s)
{
delete[] data; //如果是賦值給自身的情況,s.data也給delete了,所有後面都是錯了
data = new char[strlen(s.data)+1];
strcpy(data,s.data);
return *this;
}
所以最好:
String& String::operator=(const String& s)
{
if( &s != this){
delete[] data;
data = new char[strlen(s.data)+1];
strcpy(data,s.data);
return *this;
}
}
或:
String& String::operator=(const String& s)
{
char* newdata = new char[strlen(s.data)+1];
strcpy(newdata,s.data);
delete[] data;
data = newdata;
return *this;
}
9. 需要定義關係操作符嗎?
如果類邏輯上支援相等操作,那麼提供operate==,operate!=,就可能有好處
如果類的值有某種排序關係,那就考慮其他 < > 等操作符
10. 刪除資料用delete[]了嗎?
刪除數組是用delete[]是個好習慣。這種用法是為了與C相容,實現時會有個地方記錄數組的長度
11. 記得在複製建構函式和賦值操作符的參數類型中加const了嗎?
X::X(const X&)
X::operator=(const X&)
12. 如果函數有引用參數,它們應該是const引用嗎?
Complex operator+(const Complex& x,const Complex& y);
13. 記得適當地聲明成員函數為const了嗎?
如果一個成員函數不會修改其對象(一般get方法),可以聲明它為const,這樣它才可以應用於const對象。
例如:
int padded_length(const Vector& v,int n)
{
int k = v.length(); //由於v是const的,所以length()函數也需要定義成const,否則編譯不通過。
return k>n?k:n;
}