好吧,首先让我说这可能是非常主观和有争议的,并且可能不属于这里(如果感觉是相互的,请随意关闭)。话虽如此,我正在看一些代码,我想要一个标准的构图方法,因为看起来不同的人有不同的风格 - 所以,这是我见过的风格(可能还有更多) ..)我看到的特定组合问题是类B
拥有类A
的实例,但是,A
需要知道该实例,以便它可以调用{的方法{1}}。
B
由此,我可以看到以下内容(未完成):
转发声明 减少了在标头中包含标头的需要,但是您不能使用在该标头中声明的前向类型 - 即完整类型在使用时必须可用。
接口 额外的行李(基类构造,虚函数调用等)
模板 除了编译问题(即荒谬的错误信息等),我看不出任何问题。
现在,我赞成模板化的方法 - 我认为它很干净,并且具有强制编译时间的优点。所以问题的症结在于,这种方法在技术上是否存在问题,如果没有,为什么要采用其他两种方法呢?
有趣的是,大多数答案都建议转发,但我仍然无法理解为什么这比模板化方法更有优势 - 除了简单的通用函数之外,是否有一些固有的担心在代码中使用模板?
答案 0 :(得分:3)
您是否考虑过修复基本设计问题,以便您没有成员需要知道其父级才能运行?如果没有关于这种安排动机的更多信息,很难推荐更好的替代方案,但基本问题似乎是设计而非技术。
修改强> 听起来你正在寻找一个Service Locator。仔细看看,看看它是否无法帮助您解决设计问题。
答案 1 :(得分:1)
我会选择第一个解决方案,它完全符合您的要求。
我会考虑其他两个解决方案 workaraounds ,因为:
interfaces 是这里不需要的东西,正如你所说,它增加了复杂性和开销。
templates 不需要,你只是将它们用作hack,并且它会产生一些问题(荒谬的错误消息,所有的实现都需要在你的头文件 - 这可能会出现与其他类相同的问题 - ,...)
甚至还有第四种解决此问题的方法:easing the declare before use rule
答案 2 :(得分:0)
如果A和B在同一个头文件中声明,那么“前向”解决方案是最直接的IMO。否则,请使用“界面”解决方案。
答案 3 :(得分:0)
这不是构成,那只是继承 - 也就是说,B有效地继承自A,而且我觉得你需要重新设计你的类。
我个人使用转发解决方案,但当然,在我的课程中,B不包含A。
答案 4 :(得分:0)
这样的循环依赖关系通常表明需要重新设计设计。通常,更好的解决方案是引入第三类C
,在A
和B
之间进行调解/互动(或者A
与B
互动)。< / p>
但是,如果A
和B
确实非常紧密耦合,请使用第一个示例中的前向声明,并将两个类放在同一个标题中。
编辑(用于OP的编辑):
在这种情况下,听起来你需要一个“算法”类,它知道管理器和所有子对象,并将每个工作委托给适当的包含对象(根据需要从容器中获取)。它可以将B
的引用传递给需要它的A
方法,而不是引入循环依赖。
我认为人们更喜欢前瞻性声明,因为每个人都知道它们如何工作并理解所讨论的模式。在模板示例中,某人可能需要更长时间才能意识到模板存在的唯一原因是使用前向声明。
答案 5 :(得分:0)
在某些情况下,回调是优雅的解决方案(事件处理程序,计时器),在java中,您通常会使用嵌套类。
如果拥有的类是(或可能在功能上)是嵌套类,我会考虑前向声明。 A还有什么叫B呢?
当假设使用不同的回调是合理的时候会使用接口,但每个类只有1个(不太可能)。
否则,我会使用信号机制作为回调(观察者)
坦率地说,我没有看到模板化购买的东西,也许是因为我还没有使用它。