4

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

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

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 的指针:(ImageInfo *mpMyInfo;我想避免堆。)
  • 使用序列化并存储序列化的 ImageInfo,然后从序列化数据创建本地实例。
4

4 回答 4

3

我认为您不能拥有非静态的 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 实例存在。

于 2013-06-11T13:30:23.000 回答
2

由于它们是可以修改的数据字段,因此它们不是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它们被调用的地方,即使访问站点就像白天一样清楚地拥有它。

于 2013-06-11T13:33:06.993 回答
1

如果某些东西是 const 的,你就不能改变它。句号。

所以你必须在某个地方调整设计,要么没有那些 ImageInfo 成员 const,没有 ImageInfo 作为成员,要么最好:不做分配。

通常 const 成员在构造函数中设置。您可以创建一个加载函数来创建一个包含所有内容的 MyImageObject 对象,从而避免半途而废并在第二阶段加载状态。

另一种方法是间接使用 mMyInfo,例如使用 unique_ptr,然后您可以将其替换为另一个实例。如果没有非常好的理由,我不会那样做。

于 2013-06-11T13:26:25.683 回答
0

不可变值对象很棒。但是保存值对象的变量(MyImageObject 中的 mMyInfo)应该是(非常量)一个指针。在其他语言(例如 Java)中,这种情况会自动发生,但在 C++ 中则不然,您需要 * 运算符。此外,不需要为值对象覆盖/实现 = 运算符。要更改图像对象中的图像数据,请将新构造的 ImageInfo 对象分配给 myImageInfo 指针。这样,值对象的任何内部变量都不会改变。

于 2015-02-15T20:07:26.573 回答