2012-07-02 144 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字符串强制转换为字符串&&。 –