2012-07-02 140 views
3

爲什麼編譯器會在指定的行處發生抱怨?爲什麼我會在這段代碼中得到一個錯誤的錯誤?

class C 
{ 
    std::string s; 
public: 
    C() { s = "<not set>";} 
    ~C() {} 
    void Set(const std::string ss) { s=ss; } 
    const std::string Get() { return s; } 

    C &operator=(const C &c) { Set(c.Get()); return *this; } 
    //error: passing ‘const C’ as ‘this’ argument of ‘const string C::Get()’ 
    // discards qualifiers [-fpermissive] 


    //C &operator=(C &c) { Set(c.Get()); return *this; } <-- works fine 

}; 
+2

'-fpermissive'不是錯誤,它是一個標誌來控制生成的錯誤。請參閱[什麼是fpermissive標誌嗎?](http://stackoverflow.com/questions/8843818/what-does-the-fpermissive-flag-do) –

回答

5

您需要聲明函數Get()const

const std::string Get() const { return s; } 

即使Get()不會更改任何成員的值,編譯指示只能讓你調用了明確標記功能const

gcc指示您可以通過使用參數-fpermissive覆蓋它的投訴;但是,最好不要這樣做(或者爲什麼要聲明const?)。通常,最好確保const參數上調用的每個成員函數都是const成員函數。

這篇關於Const Correctness的文章非常有趣。

3

在你的operator =對象內c是一個常量對象:它有const C類型。在C++語言中,您不允許調用常量對象的非常量成員函數。即由於您的Get是一個非常量成員函數,致電c.Get()是非法的。這就是編譯器報告錯誤的原因。

要麼你的c非恆定(如在你的註釋版本的代碼中),要麼使Get不變。你決定哪種方法是正確的,但看起來你應該做後者。

作爲一個方面說明,沒有太多的宣佈Get()返回const std::string點。如果您通過參考返回(如const std::string &),那麼const將是適當的。但是,由於您按值返回,因此將返回類型聲明爲const並不是那麼有用。這是你個人風格的問題。

+0

關於你的sidenote:返回字符串作爲const值不會允許字符串被移動。也就是說,該值將使用std :: string的複製構造函數,而不是移動構造函數,因爲您不能將const字符串強制轉換爲字符串&&。 –