繁体   English   中英

如何为数据对象分配const成员?

[英]How do I assign a data object with const members?

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

我有一个数据对象,其数据仅在捆绑包中有效-即,在不使另一个成员无效的情况下更改一个成员的值是没有意义的。
此数据对象描述了一些图像信息:

struct ImageInfo
{
    ImageInfo(const double &ppix, ...)
        : PpiX(ppix),
        ...
    { }

    const double PpiX;
    const double PpiY;
    const int SizeX;
    const int SizeY;
};

在我的图像对象中,我具有ImageInfo类型的非常量成员:

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 *mpMyInfo;的指针: 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它们的构造后访问限制为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 ++中则不是这样,您需要*运算符。 同样,也不需要为值对象重写/实现=运算符。 要更改图像对象内的图像数据,请将新构造的ImageInfo对象分配给myImageInfo指针。 这样,值对象的内部变量都不会更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM