我有一个Data
班。该类包含2个(或更多)类OtherData
的实例。现在,OtherData
的每个实例(作为成员存储在类Data
中)具有一些共同的数据。我不希望OtherData
的每个实例都拥有它们共有的那个数据的副本。例如,OtherData
可以共享CommonData
类型的对象。
现在,我决定将公用数据存储在Data
类中。在构造时,OtherData
的实例将接收到指向Data
实例的指针,以便能够访问公用数据。我决定采用这种方式来避免实现类CommonData
。看起来更简单,更短。
一个简短的例子:
// the class which contains the common data as well as the instances of OtherData
struct Data;
struct OtherData
{
OtherData(const Data* data) : _data { data } {}
const Data* _data;
int getCommonData() const;
};
struct Data
{
Data() : _data1 { this }, _data2 { this } {}
Data(const Data&) = delete;
Data(Data&&) = delete;
Data& operator=(const Data&) = delete;
Data& operator=(Data&&) = delete;
OtherData _data1, _data2;
int getData() const { return 1; }
};
int OtherData::getCommonData() const { return _data->getData(); }
现在,从OtherData
的实例中,我可以轻松获得公用数据。
我通常避免将this
传递给成员,我讨厌循环依赖(这意味着一个对象包含另一个对象,而后者具有对前者的引用或指针)。但是,这似乎很简单,我无法证明这是一个糟糕的设计。
所以,我的问题是:您会避免这种设计吗?为什么?还是您认为可以接受?
答案 0 :(得分:0)
这是一个脆弱的设计。复制或移动最初的Data
对象(例如,按值作为参数传递),您会感到混乱。
Data
个对象处理此问题的一种方法是仅禁用复制和移动。创建Data
对象后,就无法复制或移动该对象,从而确保OtherData
中的指针保持有效。这是一种快速的解决方案,但是非常严格,但是在某些非常特定的情况下可以接受。
struct Data
{
Data() { /* .. */ }
Data(const Data&) = delete;
Data(Data&&) = delete;
Data& operator=(const Data&) = delete;
Data& operator=(Data&&) = delete;
};
每当您处理需要从多个对象访问的资源时,请考虑实现RAII的智能指针。现在,您必须在unique_ptr
和shared_ptr
之间进行选择。如果CommonData
的生存时间应与Data
个对象一样长(没有OtherData
个生存期为Data
),则可以使用unique_ptr
,否则需要{{1} }。
使用shared_ptr
的示例:
unique_ptr