(首先,对不起我的英语)
为了避免循环依赖的句法限制,我想知道以下提出的解决方案是否真的是一个解决方案,或者它是否具有比冒险更多的不满(让我认为这种相互依赖是不可避免的):
原始情况:
class B;
class A
{
B needed;
};
class B {};
输出:
B has an incomplete type.
“解决方案”:
template<typename T = class B>
class tricky_A
{
static_assert(is_same<T, B>::value, "Too tricky!!");
T needed;
};
class B {};
using A = tricky_A<>;
int main()
{
A a; // At the instantiation point, B isn't an incomplete type.
}
输出:
No problems.
常见的解决方案是使用指针,但是当你真的不需要时我会看到两个问题:
1)如果您决定保留指向其他本地对象的指针,您应该确定(或者您的类的用户应该确定)对象的生命周期短于“保留”对象的生命周期。 / p>
2)如果你决定处理动态内存,你应该花时间预留和破坏内存,而且它会强迫你处理异常处理,以使你的代码异常安全。
*)更长的代码;可读性较小;更难维持;等
我应该使用这个“解决方案”还是更好地搜索其他人?
编辑:你没事。这不是一个真正的循环依赖,所以,没有什么可以问的。这个问题可以关闭。
EDIT2 :更好的问题here。
答案 0 :(得分:1)
我认为使用指针(我同意@Andy Prowl RE:智能指针)是首选解决方案。关于你关于更长的代码,更小的可读性,更难维护的观点 - 你的“棘手”解决方案虽然聪明,但却违反了所有这些租户 - 它更长,更难阅读,更难维护。中级C ++开发人员的入门应该知道如何处理指针和智能指针,但是很难期望他们理解你提出的模板解决方案。
我也没有在你的例子中看到循环依赖;我会假设B
也取决于A
。
处理此类设计时需要记住的重要事项包括:
#includes
:正文#includes
,正向引用#includes
,最后(如有必要),标题#includes
答案 1 :(得分:1)
你设计的前提是错误的。由于代码中没有循环依赖,因此无需修复(除了在B
之前找到A
的定义),并且不需要进行额外的工作。
如果您修复测试用例以包含真正的循环依赖关系,您会发现解决方案无法解决问题。所以基本上你有更多的代码更复杂,但仍然是同样的问题。
另请注意,处理循环依赖关系的正确方法是打破它。一旦循环依赖性消失,管理它的需求也就消失了。很少有好的设计包含真正的循环依赖。