从非常量对象调用 const 函数

发布于 2024-07-11 20:12:46 字数 943 浏览 6 评论 0原文

我需要从非常量对象调用 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 的不同实例。

请继续主题。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

眼泪淡了忧伤 2024-07-18 20:12:46

const_cast 用于强制抛弃常量!

您正在从非 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();

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();
好菇凉咱不稀罕他 2024-07-18 20:12:46

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

这样做有一些迂腐的原因,但它也使您正在做的事情更加明显,而无需强迫编译器做一些可能不安全的事情。 当然,您可能永远不会遇到这些情况,但您不妨编写一些在这种情况下不使用强制转换的内容。

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.

格子衫的從容 2024-07-18 20:12:46

如果转换对您来说太难看,您可以向 Bar 添加一个方法,该方法仅返回对 *this 的 const 引用:

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

然后您可以调用 any< /em> Bar 中的 const 方法只需在前面添加 as_const().,例如:

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

If the cast is too ugly for you, you could instead add a method to Bar that simply returns a const reference to *this:

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

You can then call any const method in Bar just by prepending as_const()., e.g.:

as_const().getProcess().doSomeWork();
一刻暧昧 2024-07-18 20:12:46

如果 getProcess()getProcess() const 没有返回对同一对象的引用(但限定不同),则表明 Bar 类的设计很差。 重载函数的常量并不是区分具有不同行为的函数的好方法。

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

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

getProcess().doSomeWork();

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

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.

若有似无的小暗淡 2024-07-18 20:12:46

定义模板

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

并调用

addConst( getProcess() ).doSomeWork();

define a template

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

and call

addConst( getProcess() ).doSomeWork();
迷离° 2024-07-18 20:12:46

如果函数没有重载,则不必执行任何转换技巧。 调用非常量对象的 const 方法是可以的。 它从禁止的 const 对象调用非常量方法。 如果这些方法被 const 和非常量函数覆盖,那么将对象转换为 const 就可以解决问题:

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

编辑:我没有阅读整个问题。 是的,您需要对 this 指针进行 const_cast 或将 doOtherWork 函数设为 const 来调用 const IProcess& getProcess() 常量

重点仍然是,您不需要 const 对象来调用 doSomeWork。 既然这是目标,那么是否需要调用const方法呢?

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

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.

乖乖哒 2024-07-18 20:12:46

嗯,你能声明一下

void doOtherWork const ()

吗?

这样就可以了。

Well, can you declare

void doOtherWork const ()

?

That would do it.

长发绾君心 2024-07-18 20:12:46

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

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

I think the const_cast method is your best option. This is just a limitation of the const framework in C++. I think the only way you could avoid the casting is to define a method which returns const IProcess instance regardless. For instance.

const IProcess* getProcessConst() const { return ... }
...
getProcessConst().doSomeWork();
月下凄凉 2024-07-18 20:12:46

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

即使这有效,对我来说这看起来也很难闻。 我会非常警惕类行为根据对象的常量而发生根本变化。

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.

茶色山野 2024-07-18 20:12:46

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

IProcess& 主要通过属性在其他代码中访问,

__declspec(property(get=getProcess)) IProcess& Process;

因此不能选择重命名。 大多数情况下,调用函数的常量与 getProcess() 匹配,因此没有问题。

Posted by monjardin
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.

IProcess& is accessed in other code mostly through a property

__declspec(property(get=getProcess)) IProcess& Process;

so renaming was not an option. Majority of the time constness of the calling function matches getProcess() so there was no issue.

阳光下慵懒的猫 2024-07-18 20:12:46

对于 C++17 及更高版本,请考虑使用 std::as_const

std::as_const(getProcess()).doSomeWork()

For C++17 and later, consider using std::as_const:

std::as_const(getProcess()).doSomeWork()
残疾 2024-07-18 20:12:46

您基本上只能重命名其他方法或 const_cast。

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

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

You're basically stuck with renaming the other method or const_cast.

BTW, this is one of the reasons that copy-on-write smart pointers don't actually work well in C++. A copy-on-write smart pointer is one that can be shared infinitely. When a user accesses the data in a non-const context, a copy of the data is made (if the user doesn't hold the unique reference). This kind of pointer can be very convenient to use when sharing large data structures that only some clients need to modify. The most "logical" implementation is to have a const and a non-const operator->. The const version just returns the underlying reference. The non-const version does the unique reference check and copying. It fails to be useful because a non-const smart pointer will use the non-const operator-> by default, even if you wanted to use the const version. The const_cast requirement makes it very user-unfriendly.

I'm welcoming anyone who proves me wrong and shows a user-friendly copy-on-write pointer in C++...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文