Calling a const function from a non-const object

2020-02-05 11:57发布

I need to call a const function from a non-const object. See example

struct IProcess {
   virtual bool doSomeWork() const = 0L;
};
class Foo : public IProcess {    
  virtual bool doSomeWork() const {
    ...
  }
};

class Bar
{
public:
   const IProcess& getProcess() const {return ...;}
   IProcess& getProcess() {return ...;}

   void doOtherWork {
    getProcess().doSomeWork();        
  }
};

Calling

getProcess().doSomeWork();

will always results in a call to

IProcess& getProcess()

Is there another way to call

const IProcess& getProcess() const 

from a non constant member function? I have so far used

const_cast<const Bar*>(this)->getProcess().doSomeWork();

which does the trick but seems overly complicated.


Edit: I should mention that code is being refactored and eventually only one function will remain.

const IProcess& getProcess() const 

However, currently there is a side effect and the const call may return a different instance of IProcess some of the time.

Please keep on topic.

11条回答
闹够了就滚
2楼-- · 2020-02-05 12:35

const_cast is for casting away constness!

You're casting from non-const to const which is safe, so use static_cast:

   static_cast<const Bar*>(this)->getProcess().doSomeWork();

I mean techincally speaking you can cast in constness with const_cast, but it's not a pragmatic use of the operator. The purpose of new style casts (versus the old c-style cast), is to communicate the intent of the cast. const_cast is a code smell, and it's use should be reviewed at least. static_cast on the other hand is safe. But it's a matter of C++ style.

Or you can create a new (private) const method, and call that from doOtherWork:

  void doSomeWorkOnProcess() const { getProcess().doSomeWork(); }

Using a const temporary is also an option (answer by "MSN"):

   const Bar* _this = this;
   _this->getProcess().doSomeWork();
查看更多
ら.Afraid
3楼-- · 2020-02-05 12:39

You don't have to do any casting trickery if the function is not overloaded. Calling a const method of a non-const object is fine. It's calling a non-const method from a const object that is forbidden. If the methods are overridden with a const and non-const function, then casting the object to const will do the trick:

const_cast<const IProcess&> (getProcess()).doSomeWork();

EDIT: I didn't read the whole question. Yes, you need to const_cast the this pointer or make the doOtherWork function const to call const IProcess& getProcess() const.

The point remains that you don't need a const object to call doSomeWork. Since that is the goal, do you need the const method called?

Another option would be to rename the over-ridden functions. This would be a really good idea if the two function actually have different behavior/side-effects. Otherwise, the effect of the function call would not be obvious.

查看更多
你好瞎i
4楼-- · 2020-02-05 12:39

I assume you want DoOtherWork to call one of your two getprocess calls depending on on whether it's called from a const object or not.

The best I can suggest is this:

class Bar
{
public:
   const IProcess& getProcess() const {return ...;}
   IProcess& getProcess() {return ...;}

   void doOtherWork {            // should use getProcess()      
    getProcess().doSomeWork();        
  }
   void doOtherWork const {
    getProcess().doSomeWork();   // should use getProcess() const     
  }
};

Even if that works, this looks like a bad smell to me. I'd be very wary of the class behaviour changing radically according to the constness of an object.

查看更多
迷人小祖宗
5楼-- · 2020-02-05 12:40

Well, can you declare

void doOtherWork const ()

?

That would do it.

查看更多
等我变得足够好
6楼-- · 2020-02-05 12:43

Avoid the cast: assign this to a const Bar * or whatever and use that to call getProcess().

There are some pedantic reasons to do that, but it also makes it more obvious what you are doing without forcing the compiler to do something potentially unsafe. Granted, you may never hit those cases, but you might as well write something that doesn't use a cast in this case.

查看更多
祖国的老花朵
7楼-- · 2020-02-05 12:51

If getProcess() and getProcess() const are not returning a reference to the same object (but differently qualified) then it would indicate a poor design of class Bar. Overloading on the constness of the function is not a good way to distinguish functions with different behaviours.

If they are returning a reference to the same object then:

const_cast<const Bar*>(this)->getProcess().doSomeWork();

and

getProcess().doSomeWork();

call exactly the same doSomeWork() function so there is no need to use the const_cast.

查看更多
登录 后发表回答