从非const对象调用const函数

时间:2009-01-02 15:28:50

标签: c++ function const

我需要从非const对象调用const函数。见例子

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();        
  }
};

致电

getProcess().doSomeWork();

总是会调用

IProcess& getProcess()

还有另一种方式来致电

const IProcess& getProcess() const 

来自非常数成员函数? 我到目前为止使用

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

这可以解决问题,但似乎过于复杂。


编辑:我应该提到代码正在重构,最终只剩下一个函数。

const IProcess& getProcess() const 

但是,目前存在副作用,const调用可能会在某些时候返回不同的IProcess实例。

请继续主题。

11 个答案:

答案 0 :(得分:14)

const_cast用于投射远离 constness!

您正在从非const转换为const,这是安全的,因此请使用static_cast

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

我的意思是说技术上你可以使用const_cast强制转换为常量,但这并不是对运算符的实用性。新风格演员(与旧的C风格演员阵容相比)的目的是传达演员的意图。 const_cast是一种代码气味,至少应该对它的使用进行审核。另一方面,static_cast是安全的。但这是C ++风格的问题。

或者您可以创建一个新的(私有)const方法,并从doOtherWork

调用它
  void doSomeWorkOnProcess() const { getProcess().doSomeWork(); }

使用const临时也是一个选项(通过“MSN”回答):

   const Bar* _this = this;
   _this->getProcess().doSomeWork();

答案 1 :(得分:10)

避免演员:将其分配给const Bar *或其他任何内容并使用它来调用getProcess()

有一些迂腐的理由可以做到这一点,但它也使你在不强迫编译器做一些可能不安全的事情时更加明显。当然,你可能永远不会遇到这些情况,但你也可以在这种情况下写一些不使用演员表的东西。

答案 2 :(得分:4)

如果getProcess()getProcess() const未返回对同一对象的引用(但具有不同的限定条件),则表示class Bar的设计较差。在函数的const上重载不是区分具有不同行为的函数的好方法。

如果他们返回对同一对象的引用,则:

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

getProcess().doSomeWork();

调用完全相同的doSomeWork()函数,因此无需使用const_cast

答案 3 :(得分:3)

如果演员阵容对你来说太难看了,你可以改为向Bar添加一个只返回*this的const引用的方法:

Bar const& as_const() const {
    return *this;    // Compiler adds "const" without needing static_cast<>
}

然后,只需预先const,就可以在Bar中调用任何 as_const().方法,例如:

as_const().getProcess().doSomeWork();

答案 4 :(得分:1)

如果函数没有重载,则不必执行任何强制转换操作。调用非const对象的const方法很好。它从被禁止的const对象调用非const方法。如果使用const和非const函数覆盖这些方法,那么将对象强制转换为const将会起到作用:

const_cast<const IProcess&> (getProcess()).doSomeWork();
编辑:我没有读完整个问题。是的,您需要const_cast this 指针或使 doOtherWork 函数const调用 const IProcess&amp; getProcess()const

关键在于您不需要const对象来调用 doSomeWork 。既然这是目标,你需要名为?

的const方法吗?

另一种选择是重命名过度使用的功能。如果这两个函数实际上具有不同的行为/副作用,那将是一个非常好的主意。否则,函数调用的效果不会很明显。

答案 5 :(得分:1)

定义模板

template< class T >
const T & addConst ( T & t ) 
{
    return t;
}

并致电

addConst( getProcess() ).doSomeWork();

答案 6 :(得分:0)

嗯,你能宣布

吗?
void doOtherWork const ()

那就可以了。

答案 7 :(得分:0)

我认为const_cast方法是你最好的选择。这只是C ++中const框架的一个限制。我认为唯一可以避免转换的方法是定义一个返回const IProcess实例的方法。例如。

const IProcess* getProcessConst() const { return ... }
...
getProcessConst().doSomeWork();

答案 8 :(得分:0)

我假设您希望DoOtherWork调用您的两个getprocess调用之一,具体取决于是否从const对象调用它。

我能建议的最好的是:

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     
  }
};

即使这样可行,这对我来说也是一种难闻的气味。我会非常警惕根据对象的常量彻底改变的类行为。

答案 9 :(得分:0)

  

monjardin发布   另一种选择是重命名过度使用的函数。如果这两个函数实际上具有不同的行为/副作用,那将是一个非常好的主意。否则,函数调用的效果不会很明显。

的iProcess&安培;主要通过属性

访问其他代码
__declspec(property(get=getProcess)) IProcess& Process;

所以重命名不是一种选择。调用函数的大部分时间 const 都与getProcess()匹配,所以没有问题。

答案 10 :(得分:-1)

你基本上没有重命名其他方法或const_cast。

BTW,这是写时复制智能指针在C ++中实际上不能很好地工作的原因之一。写时复制智能指针是可以无限共享的指针。当用户访问非const上下文中的数据时,会生成数据副本(如果用户未持有唯一引用)。当共享只有一些客户端需要修改的大型数据结构时,这种指针可以非常方便地使用。最“逻辑”的实现是使用const和非const运算符 - >。 const版本只返回底层引用。非const版本执行唯一的引用检查和复制。它没有用,因为非const智能指针将使用非const运算符 - >默认情况下,即使您想使用const版本。 const_cast要求使其对用户不友好。

我欢迎任何证明我错误的人,并在C ++中展示一个用户友好的写时复制指针...