开发者

How to discard const in c++

This is what I'm trying to do and I can't:

#include <string>
using namespace std;
class A {
public:
  bool has() const { return get().length(); }
  string& get() { /* huge code her开发者_运维问答e */ return s; }
private:
  string s;
};

The error I'm getting is:

passing ‘const A’ as ‘this’ argument of
‘std::string& A::get()’ discards qualifiers

I understand what the problem is, but how can I fix it? I really need has() to be const. Thanks.


Add a second overload of get():

string const & get() const { return s; }

That will be called on a const typed object of class A.

In practice, I prefer adding only const-typed accessors, and then keeping modifications entirely internal to the class or even avoid them entirely. For example, that means having a method DoUpdateLabel(){/*do something with s*/} rather than expose the internals. That has the nice side effect that you can avoid duplicating accessors in many cases.

If you absolutely must have modification via accessors and you also don't want an extra const wrapper, you can use const_cast<>:

bool has() const { return const_cast<A*>(this)->get().length(); }

However, if get() has side-effects and has() is declared const, it's questionable whether this is behavior you really want.


I think your question is a bit vague.

You have:

bool has() const { return get().length(); }
string& get() { /* huge code here */ return s; }

... and need has() to be const.

I can think of three ways to get around this, depending on what you're actually trying to do:

The cleanest option would be for has to only use const code. If some of your /* huge code here */ code non-const but doesn't actually change the logical value of the class (like computing a cached internal value) consider using mutable on the data involved.

If the /* huge code here */ part is non-const by nature, consider refactoring it into a different function and calling it separately:

using namespace std;
class A {
public:
  bool has() const { return get().length(); }
  const string& get() const {  return s; }
  void computestuff() { /* huge code here */ }
private:
  string s;
};

A  instance;

// old client code:
// string s = instance.get();
//
// new code:
instance.computestuff(); // non-const call
instance.get(); // const call
instance.has(); // const call

Ultimately, you can also cast the const-ness away (but keep in mind that the need to do so is almost always a sign of bad design/need to refactor):

class A {
public:
  bool has() const { return const_cast<A*>(this)->get().length(); }
  string& get() { /* huge code here */ return s; }
private:
  string s;
};


It's pretty usual to have const and non-const versions of the same functions.

So, one of them would be called if your object is called as a const object, and the second - if the same happens with a non-const.

I have to mention, that this technique usually is used with operators but is also suitable for you current case.


Also, in your current case the best approach could mean having ONLY const method like

const string& get() const { return s }

and refactoring all your other code so it works with a string returned via constant reference.


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

because passing strings by value is usually cheap (I don't remember if this is a guarantee), and I don't think you want the string you're looking at to change under your feet when A modifies it.


Try this:

const string& get() const { return s; }

The first const applies to the return type of the method get(). The return type is a reference to a string. Altogether it's a const reference to a string, which enforces that this returb value is not to be changed.

The second const applies to the method, effectively making it a const method.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜