允许成员为常量,同时仍然支持类上的operator=
我的类中有几个成员是 const,因此只能通过初始化列表进行初始化,如下所示:
class MyItemT
{
public:
MyItemT(const MyPacketT& aMyPacket, const MyInfoT& aMyInfo)
: mMyPacket(aMyPacket),
mMyInfo(aMyInfo)
{
}
private:
const MyPacketT mMyPacket;
const MyInfoT mMyInfo;
};
我的类可以在一些内部定义的容器类(例如向量)中使用,并且这些容器要求在类中定义 operator=
。
当然,我的operator=需要做这样的事情:
MyItemT&
MyItemT::operator=(const MyItemT& other)
{
mMyPacket = other.mPacket;
mMyInfo = other.mMyInfo;
return *this;
}
这当然不起作用,因为mMyPacket
和mMyInfo
是const成员。
除了使这些成员成为非 const(我不想这样做)之外,还有关于如何解决此问题的任何想法吗?
I have several members in my class which are const
and can therefore only be initialised via the initialiser list like so:
class MyItemT
{
public:
MyItemT(const MyPacketT& aMyPacket, const MyInfoT& aMyInfo)
: mMyPacket(aMyPacket),
mMyInfo(aMyInfo)
{
}
private:
const MyPacketT mMyPacket;
const MyInfoT mMyInfo;
};
My class can be used in some of our internally defined container classes (e.g. vectors), and these containers require that operator=
is defined in the class.
Of course, my operator=
needs to do something like this:
MyItemT&
MyItemT::operator=(const MyItemT& other)
{
mMyPacket = other.mPacket;
mMyInfo = other.mMyInfo;
return *this;
}
which of course doesn't work because mMyPacket
and mMyInfo
are const
members.
Other than making these members non-const
(which I don't want to do), any ideas about how I could fix this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
如果您有一个赋值运算符可以在构造完成后更改它们,那么您就违反了 const 的定义。如果你真的需要,我认为 Potatoswatter 的放置新方法可能是最好的,但是如果你有一个赋值运算符,你的变量并不是真正的 const,因为有人可以创建一个新实例并使用它来更改它们的值
You're kind of violating the definition of const if you have an assignment operator that can change them after construction has finished. If you really need to, I think Potatoswatter's placement new method is probably best, but if you have an assignment operator your variables aren't really const, since someone could just make a new instance and use it to change their values
您可以存储指针(或智能指针),而不是直接在容器中存储对象。这样,您不必更改类的任何成员 - 您将返回与传入的对象完全相同的对象、
const
等。当然,这样做可能会在一定程度上改变应用程序的内存管理,这很可能是不想这样做的充分理由。
Rather than storing objects in your containers directly, you might be able to store pointers (or smart pointers). That way, you don't have to mutate any of the members of your class -- you get back exactly the same object as you passed in,
const
and all.Of course, doing this will probably change the memory management of your application somewhat, which may well be a good enough reason not to want to.
这是一个肮脏的黑客行为,但你可以自己销毁和重建:
编辑:以免破坏我的可信度,我自己实际上不会这样做,我会删除
const
。然而,我一直在争论改变这种做法,因为 const 非常有用,并且尽可能使用更好。有时,资源和对象表示的值之间存在区别。只要资源相同,成员就可以通过值的更改而成为 const,并且最好能够获得编译时安全性。
编辑2:@Charles Bailey提供了这个精彩的(并且非常关键的)链接: http://gotw.ca/gotw/023.htm。
operator=
中,语义都很棘手。operator&
重载(无论什么)不兼容。 编辑 3: 通过思考“哪个资源”与“什么值”的区别,似乎很清楚
operator=
应该始终更改值而不是资源。那么资源标识符可以是const。在该示例中,所有成员都是const
。如果“信息”是存储在“数据包”内的内容,那么数据包可能应该是 const 而信息不是。因此,如果“信息”实际上是元数据,那么问题不在于弄清楚分配的语义,而在于在此示例中缺乏明显的值。如果拥有
MyItemT
的任何类想要将其从一个数据包切换到另一个数据包,则需要放弃并使用auto_ptr
代替,或者诉诸类似的方法如上所述的 hack(身份测试是不必要的,但catch
仍然存在)从外部实现。但是operator=
不应该更改资源绑定,除非作为绝对不会干扰其他任何内容的额外特殊功能。请注意,此约定与萨特关于在分配方面实施副本构造的建议很好地配合。
It's a dirty hack, but you can destroy and reconstruct yourself:
Edit: lest I destroy my credibility, I don't actually do this myself, I would remove the
const
. However, I've been debating changing the practice, becauseconst
simply is useful and better to use wherever possible.Sometimes there is a distinction between the resource and the value represented by an object. A member may be const through changes to value as long as the resource is the same, and it would be nice to get compile-time safety on that.
Edit 2: @Charles Bailey has provided this wonderful (and highly critical) link: http://gotw.ca/gotw/023.htm.
operator=
.operator&
overloads (whatever)Edit 3: Thinking through the "which resource" vs "what value" distinction, it seems clear that
operator=
should always change the value and not the resource. The resource identifier may then beconst
. In the example, all the members areconst
. If the "info" is what's stored inside the "packet," then maybe the packet should beconst
and the info not.So the problem isn't so much figuring out the semantics of assignment as lack of an obvious value in this example, if the "info" is actually metadata. If whatever class owns a
MyItemT
wants to switch it from one packet to another, it needs to either give up and use anauto_ptr<MyItemT>
instead, or resort to a similar hack as above (the identity test being unnecessary but thecatch
remaining) implemented from outside. Butoperator=
shouldn't change resource binding except as an extra-special feature which absolutely won't interfere with anything else.Note that this convention plays well with Sutter's advice to implement copy construction in terms of assignment.
我认为你可以使用特殊的
const
代理。现在,您将拥有
Const
,而不是const MyPacketT
。并不是说该接口只提供了一种更改它的方法:通过显式调用reset
。我认为任何
mMyPacket.reset
的使用都可以很容易地被搜索到。正如 @MSalters 所说,它可以防止墨菲,而不是马基雅维利:)I think you could get away with a special
const
proxy.Now, instead of
const MyPacketT
you would haveConst<MyPacketT>
. Not that the interface only provides one way to change it: through an explicit call toreset
.I think any use of
mMyPacket.reset
can easily be search for. As@MSalters
said it protects against Murphy, not Machiavelli :)您可以考虑将
MyPacketT
和MyInfoT
成员设置为指向const
的指针(或指向const
的智能指针)。这样,数据本身仍然被标记为 const 和不可变的,但如果有意义的话,您可以在赋值中干净地“交换”到另一组 const 数据。事实上,您可以使用交换习惯以异常安全的方式执行分配。因此,您可以利用 const 来帮助您防止意外允许您希望设计阻止的更改,但您仍然允许从另一个对象分配整个对象。例如,这将允许您在 STL 容器中使用此类的对象。
您可能会将其视为“pimpl”习语的特殊应用。
最后
,我将示例更改为使用
scoped_ptr
而不是shared_ptr
因为我认为它是更通用的表示OP 的意图。然而,如果“可重新分配”的const
成员可以共享(考虑到我对为什么 OP 希望它们const
的理解,这可能是真的),那么这可能是一种优化使用shared_ptr<>
并让shared_ptr<>
类的复制和赋值操作处理这些对象的事务 - 如果您没有其他成员需要特殊的副本或分配语义,那么您的类就会变得更加简单,并且您甚至可以通过共享MyPacketT
和MyInfoT< 的副本来节省大量内存使用量/代码> 对象。
You might consider making the
MyPacketT
andMyInfoT
members be pointers toconst
(or smart pointers toconst
). This way the data itself is still marked const and immutable, but you can cleanly 'swap' to another set of const data in an assignment if that makes sense. In fact, you can use the swap idiom to perform the assignment in an exception safe manner.So you get the benefit of
const
to help you prevent accidentally allowing changes that you want the design to prevent, but you still allow the object as a whole to be assigned from another object. For example, this will let you use objects of this class in STL containers.You might look at this as a special application of the 'pimpl' idiom.
Something along the lines of:
Finally, I changed my example to use
scoped_ptr<>
instead ofshared_ptr<>
because I thought it was a more general representation of what the OP intended. However, if the 'reassignable'const
members can be shared (and that's probably true, given my understanding of why the OP wants themconst
), then it might be an optimization to useshared_ptr<>
's and let the copy and assignment operations of theshared_ptr<>
class take care of things for those objects - if you have no other members that require special copy or assign sematics, then your class just got a lot simpler, and you might even save a significant bit of memory usage by being able to share copies of theMyPacketT
andMyInfoT
objects.