-1

(首先,对不起我的英语)

为了避免循环依赖的句法限制,我想知道下面提出的解决方案是否真的是一个解决方案,或者它是否有比冒险更多的缺点(假设这种相互依赖是不可避免的):

原来情况:

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)如果您决定保留指向其他本地对象的指针,您应该确定(或您的类的用户应该确定)您的对象的生命周期比“保留”对象的生命周期短。

2)如果你决定处理动态内存,你应该花时间保留和销毁内存,而且它迫使你处理异常处理,以使你的代码异常安全。

*) 更长的代码;较小的可读性;更难的保养;等等

我应该使用这个“解决方案”还是更好地搜索另一个?

编辑:你没事。这不是真正的循环依赖,所以没有什么可问的。这个问题可以关闭。

EDIT2: 一个更好的问题在这里

4

2 回答 2

1

我认为使用指针(我同意@Andy Prowl RE:智能指针)是首选解决方案。关于您关于更长的代码,更小的可读性,更难的维护的观点-您的“棘手”解决方案虽然聪明,但违反了所有这些租户-它更长,更难阅读,更难维护。中级 C++ 开发人员的入门应该知道如何处理指针和智能指针,但是很难期望他们理解您提出的模板解决方案。

在您的示例中,我也没有看到循环依赖;不过,我假设这B也取决于A

处理这种设计时要记住的重要事项是:

  • 分离标题和正文很有帮助
  • 更喜欢#includes按以下顺序执行: body #includes, forward-reference #includes,最后(如果需要),header#includes
于 2013-04-11T16:32:22.773 回答
1

你设计的前提是错误的。由于您的代码中没有循环依赖,因此没有什么需要修复(除了定位Bbefore的定义A)并且不需要做额外的工作。

如果你修复你的测试用例以包含一个真正的循环依赖,你会发现你的解决方案没有解决它。所以基本上你有更多更复杂的代码,但仍然是同样的问题。

另请注意,处理循环依赖的正确方法是破坏它。一旦循环依赖消失了,管理它的需求也消失了。很少有好的设计包含真正的循环依赖。

于 2013-04-11T16:50:41.200 回答