2012-01-16 46 views
5

我有一個類沒有被類的方法改變,所以我把它標記爲const。我的問題是,我正在使用默認賦值運算符就像複製構造函數,以避免多個聲明。但在這種情況下,賦值運算符不會自動生成,所以我得到一些編譯器錯誤: 'operator =' function is unavailable。這看起來似乎沒有真正的生活場景,其中可以實際使用const類成員(例如,你是否看到過STL代碼中的任何const成員?)。當賦值運算符重載時,const類成員是否有用?

有沒有什麼辦法解決這個問題,除去const

編輯:一些代碼

class A 
{ 
public : 
    const int size; 
    A(const char* str) : size(strlen(str)) {} 
    A() : size(0) {} 
}; 


A create(const char* param) 
{ 
    return A(param); 
} 


void myMethod() 
{ 
    A a; 

    a = create("abcdef"); 
    // do something 

    a = create("xyz"); 
    // do something 
} 
+0

我將標題編輯爲一些我認爲更貼近你的意思的東西,並且會鼓勵更多有用的答案。如果您不同意,請隨時將其改回。 – Crashworks 2012-01-16 07:46:22

+0

@Crashworks謝謝! – 2012-01-16 07:53:35

回答

3

這是你的誤解,這是造成這個問題:

[..]未由類

成員變量的方法改變時,通過類,賦值操作符的方法改變。包括由編譯器合成的那個。如果將成員變量標記爲const,則表示該變量將(不應該)在對象的生命週期中更改其值。很明顯,爲對象分配一個新值違反了這個說法。所以如果你確實不希望這個成員改變,那麼就不要使它成爲const

1

是的,你可以重寫賦值運算符。

因爲您使用的是默認值,編譯器也會嘗試複製const成員。這是非法的,因爲它是const

class A 
{ 
private: 
    const int a; 
public : 
    A() : a(0) {} 
    A& operator = (const A& other) {return *this;} 
}; 

int main() 
{ 
    A a; 
    A b; 
    a = b; //this is legal if operator = is declared 
} 
+2

所以const成員的價格是你可以提供一個賦值操作符,但只有一個破壞的操作符? – UncleBens 2012-01-16 07:48:35

+1

@UncleBens爲什麼這是壞的?不是,它只是不修改'const'成員......這應該是有道理的,對吧? – 2012-01-16 07:50:55

+1

@UncleBens:鑑於lhs上的const成員很可能與'rhs'上的一樣,因爲它只在構造函數中設置,所以沒有必要複製它。如果它在不同的構造函數中被初始化,那麼你可能希望重新考慮你的設計! – Johnsyweb 2012-01-16 07:53:17

2

const成員是很多,很多情況下的理想選擇。當然,明顯的情況是值不應該也不能改變,但它也是優化和併發的重要限制 - 並非每個類型都需要或應該有一個賦值運算符。

如果成員需要賦值行爲,那麼變量不能是const

當值/成員不能突變或通過this突變,它更清晰,以提供可變部件的獨立接口(或甚至一個亞型>組合物在更復雜的情況下):

class t_text { 
public: 
// ... 
public: 
    void setString(const std::string& p); 
private: 
    const t_text_attributes d_attributes; 
    std::string d_string; 
}; 

因此,我的建議是隱藏賦值運算符,並且使「可變塊」或成員設置能夠爲清楚:

text.setString("TEXT"); // << Good: What you read is what happens. 
text = otherText; // << Bad: Surprise - attributes don't actually change! 
+4

優化和併發是使用'const'我能想到的最不重要的原因。我想說,讓你不要去想愚蠢的事情(或者至少迫使你對拋棄常量感到有點內疚),這更加重要。 – 2012-01-16 08:11:30

+0

@Frerich也許這是我的錯誤,但假設使用'const'是最明顯的原因。我會更新以避免混淆。 – justin 2012-01-16 08:26:33

2

您不能有const成員和支持分配,至少不是 賦值與預期的語義。在邏輯上,const是一個 promiss該成員將永遠不會改變,並且任務是 (隱含地,在大多數人的頭腦中)一個promiss,所有數據 成員將採取右邊的成員的值 (這通常意味着改變)。這兩個promisses之間有一個非常明確的衝突 。

當然,很多類型不應該支持分配開始; 對於不支持賦值的類型,聲明 數據成員const沒有問題。但總體而言,我發現const很多 在這裏不太有用; const是合同的一部分,數據成員 通常不是班級的外部合同的一部分。 (但是很多 取決於—如果數據成員是公共的或受保護的,那麼事實 ,它是不可變的可能是外部合同的一部分。和 當然,沒有什麼不妥表達語言結構內部類不變 , )

+1

「你不能」 - 嗯,你可以,但是你必須定義一個自定義任務。例如,由X分配的邏輯上可分配的對象可以包含一個指向X的常量指針,以幫助請求X釋放該對象。例如,這樣的事情可能會解決現有框架帶來的一些問題。指針在對象的生命週期內是不變的,並且不會作爲邏輯對象狀態的一部分公開。即它不會成爲外部賦值狀態的一部分。乾杯&hth。, – 2012-01-16 11:56:53