常量类成员,赋值运算符和QList

pro*_*cer 5 c++ qt assignment-operator qlist class-constants

请确认我是否正确并告诉我是否有更好的解决方案:

我理解具有常量成员的对象int const width;不能由编译器隐式创建的合成赋值运算符处理.但是QList(我想std :: list)也需要一个工作赋值运算符.因此,当我想使用具有常量成员和QList的对象时,我有三种可能性:

  1. 不要使用常数成员.(不是解决方案)
  2. 实现我自己的赋值运算符.
  3. 使用一些不需要赋值运算符的其他容器

那是对的吗?还有其他优雅的解决方案?

我也想知道我是否可以:

  • (4)强制编译器创建一个处理常量成员的赋值运算符!(我不明白为什么这是一个很大的问题.为什么操作员不够智能,不能在内部使用初始化列表?或者我错过了什么?)
  • (5)告诉QList我永远不会在列表中使用赋值操作.

编辑:我自己从不分配这个类的对象.它们仅由复制构造函数或重载的构造函数创建.因此,只有容器才需要赋值操作符而不是我自己.

EDIT2:这是我创建的赋值运算符.我不确定它是否正确.Cell有两个参数构造函数.这些参数使用初始化列表设置两个常量成员.但该对象还包含其他变量(非常量)成员.

Cell& Cell::operator=(Cell const& other)
{
 if (this != &other) {
  Cell* newCell = new Cell(other.column(), other.row());
  return *newCell;
 }
 return *this;
}
Run Code Online (Sandbox Code Playgroud)

EDIT3:我发现这个帖子几乎有同样的问题:C++:STL麻烦与const类成员所有答案结合在一起回答了我的问题.

fre*_*low 8

您可能是C++的新手,并希望它的行为类似于Python,Java或C#.

将不可变Java对象放入集合中是很常见的.这是有效的,因为在Java中,您并不真正将Java 对象放入集合中,而只是将Java 引用放在Java对象中.更准确地说,集合内部由Java引用变量组成,并且分配给这些Java引用变量根本不会影响引用的Java对象.他们甚至没有注意到.

我故意说"Java对象","Java引用"和"Java变量",因为术语"对象","引用"和"变量"在C++中有完全不同的含义.如果你想要可变T变量,你需要可变T对象,因为变量和对象在C++中基本相同:

变量由对象的声明引入.变量的名称表示对象.

在C++中,变量不包含对象 - 它们对象.分配给变量意味着更改对象(通过调用成员函数operator=).没有其他办法了.如果你有一个不可变对象,然后分配a = b 不能可能没有明确的破坏类型系统的工作,如果你这样做,那么你已经有效地骗你的客户关于对象是不可改变的.做出承诺然后故意破坏它是没有意义的,不是吗?

当然,您可以简单地模拟Java方式:使用指向不可变对象的指针集合.这是否是一个有效的解决方案取决于您的对象真正代表什么.但仅仅因为它在Java中运行良好并不意味着它在C++中运行良好.在C++中没有不可变值对象模式.这在Java中是一个好主意,在C++中是一个糟糕的主意.

顺便说一句,你的赋值操作符完全是非惯用的并且会泄漏内存.如果您认真学习C++,那么您应该阅读其中一本书.


pro*_*cer 2

我将尝试将答案简单地捆绑在一起:

主要问题是 QList 要求存在赋值运算符,因为它们内部使用赋值。因此,他们将实现与接口混合在一起。因此,尽管您不需要赋值运算符,但没有它 QList 将无法工作。来源

@ 3.有std::List,但它不提供对元素的恒定时间访问,而QList则提供。

@ 2. 可以通过使用复制构造函数和所需属性创建一个新对象并返回它*。虽然你规避了 const 属性,但它仍然比根本不使用 const 更好,因为你允许容器在这里作弊,但仍然阻止用户自己执行此操作,这就是使该成员常量的初衷。

但请考虑到,创建重载的赋值运算符会增加代码的复杂性,并且可能会引入比成员 cons-ing 首先解决的错误更多的错误。

@ 1.最后这似乎是最简单的解决方案。只要它是私有的,您只需注意对象本身不会改变它。

@4.没办法强迫他。他不知道如何做,因为变量是常量,并且在某些时候他必须处理this->row = other.row先前int const row;定义的变量。即使在这种情况下,const 也意味着常数。一个来源

@ 5 QList 没有此类选项。

附加解决方案:

  • 使用指向对象的指针而不是纯对象

*目前对此还不确定。