3

Why would the compiler complain at the indicated line?

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

};
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
slashmais
  • 7,069
  • 9
  • 54
  • 80
  • 2
    `-fpermissive` is not an error, it is a flag to control generated errors. See [What does the fpermissive flag do?](http://stackoverflow.com/questions/8843818/what-does-the-fpermissive-flag-do) – Jonathon Reinhart Jul 02 '12 at 23:16

2 Answers2

5

You need to declare the function Get() to be const:

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

Even though Get() doesn't change any member values, the compiler is instructed to only let you call functions that are explicitly labeled const.

gcc is instructing you that you can override it's complaint by using the argument -fpermissive; however, it's generally better not to do this (or else why declare anything const at all?). Generally, it's better to make sure every member function called on a const parameter is a const member function.

This article concerning Const Correctness is very interesting.

slashmais
  • 7,069
  • 9
  • 54
  • 80
user
  • 7,123
  • 7
  • 48
  • 90
3

Inside your operator = object c is a constant object: it has const C type. In C++ language you are not allowed to call non-constant member functions of constant objects. I.e. calling c.Get() is illegal since your Get is a non-constant member function. This is why the compiler reports an error.

Either make your c non-constant (as in your commented-out version of the code), or make Get constant. It is up to you to decide which approach is right, but it looks like you should do the latter.

As a side note, there's not much point of declaring Get() as returning const std::string. If you were returning it by reference (as const std::string &) then that const would be appropriate. But since you are returning by value, declaring the return type as const is not that useful. It is a matter of your personal style though.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Regarding your sidenote: returning the string as a const value doesn't allow the string to be moved. That is, the value will use the copy constructor of std::string and not the move constructor since you can't cast const string to string&&. – Jens Åkerblom Dec 30 '15 at 08:57