如何赋值具有const成员的数据对象



希望这不是重复的。如果有,请在评论中指出,我将再次删除该问题。

我有一个数据对象,它的数据只在bundle中有效——也就是说,改变一个成员的值而不使其他成员无效是没有意义的。
这个数据对象描述了一些图像信息:

struct ImageInfo
{
    ImageInfo(const double &ppix, ...)
        : PpiX(ppix),
        ...
    { }
    const double PpiX;
    const double PpiY;
    const int SizeX;
    const int SizeY;
};
在我的图像对象中,我有一个类型为ImageInfo: 的非const成员。
class MyImageObject
{
    ...
private:
    ImageInfo mMyInfo;
}

我希望能够在运行时改变mMyInfo,但只是这样,它将采取一个新的ImageInfo(…)实例。

MyImageObject::Load()函数中,我想从文件信息中读取此数据,然后使用正确的数据集创建ImageInfo实例:

double ppix = ImageFile.GetPpiX();
...
mMyInfo = ImageInfo(ppix, ...);

但是我不能写一个有效的赋值操作符(复制构造函数当然是可能的)。我的解决方案使mMyInfo空,因为我没有引用this:

ImageInfo operator=(const ImageInfo &other)
{
    // no reference to *this
    return ImageInfo(other);
}

出于好奇,我想知道这样一个类的赋值操作符应该是什么样的。

我使用的是普通c++。

编辑
可能的解决方案(目标是保持数据可传输,但一致):

  • 使用私有成员和Get...()函数->简单,但我想避免括号。
  • 存储指向ImageInfo: ImageInfo *mpMyInfo;的指针(我想避免堆)
  • 使用序列化并存储序列化的ImageInfo,然后从序列化的数据创建本地实例。

我不认为你可以有非静态的const成员变量。如果需要随实例变化的const变量,可以这样做:

struct ImageInfo
{
private:
    double myPpiX;
    double myPpiY;
    int mySizeX;
    int mySizeY
public:
    ImageInfo(const double &ppix, ...)
        : myPpiX(ppix),
          PpiX(myPpiX),
        ...
    { }
    ImageInfo( const ImageInfo &other)
    : myPpiX( other.myPpiX),
      PpiX(myPpiX)
     ...
    { }
    const double &PpiX;
    const double &PpiY;
    const int &SizeX;
    const int &SizeY;
    // EDIT: explicit assignment operator was missing
    ImageInfo& operator=(const ImageInfo &other)
    {
        myPpiX  = other.myPpiX;
        myPpiY  = other.myPpiX;
        mySizeX = other.mySizeX;
        mySizeX = other.mySizeX;
        return *this;
    }
};

值存储在私有变量中,可以在构造时设置,它们的值通过const引用访问。您也不依赖于传递给构造函数的引用与ImageInfo实例一样长。

因为它们是可以修改的数据字段,所以它们不是const

如果您想将对它们的构造后访问限制为const,则需要将它们包装在访问器中,如下所示:

struct ImageInfo
{
  ImageInfo(const double &ppix, /*...*/)
    : PpiX_(ppix),
    /*...*/
  { }
  double const& PpiX() const {return PpiX_; };
  double const& PpiY() const {return PipY_; };
  int const& SizeX() const {return SizeX_; };
  int const& SizeY() const {return SizeY_; };
private:
  double PpiX_;
  double PpiY_;
  int SizeX_;
  int SizeY_;
};

允许移动/复制赋值和构造,同时阻止该构造之外的非const访问。

避免()是棘手的,但可以用伪引用来完成,像这样:

struct pseudo_const_reference_to_Ppix {
  ImageInfo const* self;
  operator double() const { return self->Ppix; }
  void reseat( ImageInfo const* o ) { self = o; }
};

再加上一大堆样板文件来重载左边和右边的每个const操作符,使上面的pseudo_const_reference_*double一样有效。

可以编写泛型版本(如果愿意承受类型擦除开销,可以使用函子或std::function)。

然后在赋值和复制/移动构造中维护这些伪const引用。

我认为()是更好的选择。

请注意,每个伪引用的指针(或更多)开销基本上是不可避免的:成员变量不能访问调用它们的this,即使访问站点在那里有它。

如果某项是const,则不能更改它。句号。

所以你必须在某个地方调整设计,要么不让ImageInfo成员const,不把ImageInfo作为成员,或者最好:不做赋值。

通常在构造函数中设置const成员。你可以创建一个加载函数来创建一个MyImageObject对象和它的所有内容,这样就避免了做了一半的事情而在第二阶段加载安全文件。

另一种方法是间接地拥有mMyInfo,比如使用unique_ptr,然后你可以用另一个实例替换它。如果没有很好的理由,我是不会那样做的。

不可变值对象很棒。但是保存值对象的变量(MyImageObject中的mMyInfo)应该是一个指针(非常量)。在其他语言(例如Java)中,这是自动的,但在c++中不是这样,在c++中你需要*操作符。同样,也不需要覆盖/实现值对象的=操作符。要更改图像对象中的图像数据,您可以将新构造的ImageInfo对象分配给myImageInfo指针。这样,就不会改变value对象的任何内部变量。

最新更新