[英]Why forward declaration and pointer (or reference?) can resolve circular dependency?
[英]How can I resolve a circular class dependency when forward declaration is not possible as elegantly as possible?
我有这样的事情:
struct v_with_holder {
// bunch of fields
holder h; // does not name a type
};
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
我最近才添加了此特定变体。 其他所有代码都具有标准的,已经定义的数据类型和类,因此可以复制构造它们,并且代码库可以这样编写(例如,调用ss.push_back(v)
)。
问题是,直到我声明holder
,我才能声明v_with_holder
,反之亦然。 前瞻性声明class holder;
给出field 'h' has incomplete type 'holder'
。
我以为我可以使用unique_ptr
:
class holder;
struct v_with_holder {
// bunch of fields
std::unique_ptr<holder> ph;
holder& h;
v_with_holder();
~v_with_holder();
};
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
v_with_holder::v_with_holder() : ph(new holder), h(*ph) { }
v_with_holder::~v_with_holder() { }
但是,现在的问题是v_with_holder
不再是可复制构造的:
holder h1, h2;
v_with_holder x;
x.h = h2;
h1.ss.push_back(x); // error: use of deleted function 'v_with_holder::v_with_holder(const v_with_holder&)'
现在看来,我唯一的求助方法就是定义复制构造函数,这些复制构造函数将创建新的唯一ptrs并复制内容。 为了完整起见,也请移动构造函数。 这似乎可行( ideone link ),但这意味着我从我的意图中得到了帮助,这是这样的:
struct v_with_holder {
// bunch of fields
holder h;
}
// define struct_v, holder
对于这个可怕的事情:
class holder;
struct v_with_holder {
// a bunch of fields
std::unique_ptr<holder> ph;
holder& h;
friend void swap(v_with_holder& first, v_with_holder& second)
{
using std::swap;
// swap a bunch of fields
swap(first.ph, second.ph);
}
v_with_holder();
~v_with_holder();
v_with_holder(const v_with_holder& other);
v_with_holder(v_with_holder&& other);
v_with_holder& operator=(v_with_holder other);
};
// define struct_v, holder
v_with_holder::v_with_holder() : ph(new holder), h(*ph) { }
v_with_holder::~v_with_holder() { }
v_with_holder::v_with_holder(const v_with_holder& other) : ph(new holder), h(*ph)
{
// copy a bunch of fields
h = other.h;
}
v_with_holder::v_with_holder(v_with_holder&& other) : v_with_holder()
{
swap(*this, other);
}
v_with_holder& v_with_holder::operator=(v_with_holder other)
{
swap(*this, other);
return *this;
}
一切都是为了避免循环依赖!
当然,必须有更好的方法。 告诉我有更好的方法。 请。 这是什么更好的方法?
为什么不简单地做:
struct v_with_holder {
// bunch of fields
holder *h; //Pointer to holder is of known size
};
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
好的,看来我可以转发声明v_with_holder
:
struct v_with_holder;
typedef boost::variant</* such types, */v_with_holder/*, many others */> struct_v;
class holder { public: std::vector<struct_v> ss; };
struct v_with_holder
{
holder h;
};
我没有意识到typedef
可以与前向声明的类型一起使用,或者std::vector
可以采用未声明的类型。 根据这个问题和答案 ,我认为它不可能,但是到目前为止,它已经在ideone,G ++ 4.8.1和MSVC 2012上奏效。
问题仍然存在,如果这不可能。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.