从非常量对象调用 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 的不同实例。
请继续主题。
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
const_cast
用于强制抛弃常量!您正在从非 const 转换为安全的 const,因此请使用
static_cast
:我的意思是从技术上讲,您可以使用
const_cast
进行常量转换,但事实并非如此运算符的实用使用。 新样式强制转换(与旧的 c 样式强制转换相比)的目的是传达强制转换的意图。const_cast
是一种代码味道,至少应该审查它的使用。 另一方面,static_cast
是安全的。 但这是 C++ 风格的问题。或者您可以创建一个新的(私有)const 方法,并从
doOtherWork
调用该方法:使用 const 临时也是一种选择(由“MSN 回答”) ”):
const_cast
is for casting away constness!You're casting from non-const to const which is safe, so use
static_cast
: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
:Using a const temporary is also an option (answer by "MSN"):
避免强制转换:将其分配给
const Bar *
或其他内容,并使用它来调用getProcess()
。这样做有一些迂腐的原因,但它也使您正在做的事情更加明显,而无需强迫编译器做一些可能不安全的事情。 当然,您可能永远不会遇到这些情况,但您不妨编写一些在这种情况下不使用强制转换的内容。
Avoid the cast: assign this to a
const Bar *
or whatever and use that to callgetProcess()
.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.
如果转换对您来说太难看,您可以向
Bar
添加一个方法,该方法仅返回对*this
的 const 引用:然后您可以调用 any< /em>
Bar
中的const
方法只需在前面添加as_const().
,例如:If the cast is too ugly for you, you could instead add a method to
Bar
that simply returns a const reference to*this
:You can then call any
const
method inBar
just by prependingas_const().
, e.g.:如果
getProcess()
和getProcess() const
没有返回对同一对象的引用(但限定不同),则表明 Bar 类的设计很差。 重载函数的常量并不是区分具有不同行为的函数的好方法。如果它们返回对同一对象的引用,则:
并
调用完全相同的
doSomeWork()
函数,因此无需使用const_cast
。If
getProcess()
andgetProcess() const
are not returning a reference to the same object (but differently qualified) then it would indicate a poor design ofclass Bar
. Overloading on theconst
ness 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:
and
call exactly the same
doSomeWork()
function so there is no need to use theconst_cast
.定义模板
并调用
define a template
and call
如果函数没有重载,则不必执行任何转换技巧。 调用非常量对象的 const 方法是可以的。 它从禁止的 const 对象调用非常量方法。 如果这些方法被 const 和非常量函数覆盖,那么将对象转换为 const 就可以解决问题:
编辑:我没有阅读整个问题。 是的,您需要对 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:
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.
嗯,你能声明一下
吗?
这样就可以了。
Well, can you declare
?
That would do it.
我认为 const_cast 方法是你最好的选择。 这只是 C++ 中 const 框架的限制。 我认为避免强制转换的唯一方法是定义一个无论如何都返回 const IProcess 实例的方法。 例如。
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.
我假设您希望 DoOtherWork 调用两个 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:
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.
IProcess& 主要通过属性在其他代码中访问,
因此不能选择重命名。 大多数情况下,调用函数的常量与 getProcess() 匹配,因此没有问题。
IProcess& is accessed in other code mostly through a property
so renaming was not an option. Majority of the time constness of the calling function matches getProcess() so there was no issue.
对于 C++17 及更高版本,请考虑使用
std::as_const
:For C++17 and later, consider using
std::as_const
:您基本上只能重命名其他方法或 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++...