我需要从非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实例。

请继续主题。

有帮助吗?

解决方案

避免强制转换:将其分配给 const Bar * 或其他任何内容,并使用它来调用 getProcess()

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

其他提示

const_cast 用于投射 constness!

你从非const转换为const是安全的,所以使用 static_cast

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

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

或者你可以创建一个新的(私有)const方法,并从 doOtherWork 调用它:

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

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

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

如果 getProcess() getProcess()const 没有返回对同一对象的引用(但是不同的限定),那么它将指示 class Bar 。在函数的 const 上重载不是区分具有不同行为的函数的好方法。

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

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

getProcess().doSomeWork();

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

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

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

然后,您可以通过在 as_const()。之前调用 Bar 中的任何 const 方法,例如:

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

如果函数没有重载,则不必执行任何强制转换操作。调用非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方法吗?

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

定义模板

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

并致电

addConst( getProcess() ).doSomeWork();

嗯,你能宣布

吗?
void doOtherWork const ()

那就可以了。

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

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

我假设您希望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     
  }
};

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

  

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

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

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top