![](/img/trans.png)
[英]Do non const internal members of class become const when I have const ref to an object of that class?
[英]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;
(我想避免堆。) 我认为您不能拥有非静态的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.