如果我有一个Container
类,其中包含一堆Component
个对象(类似于Java的UI框架),那么追踪Container
父级是不是很差的风格/做法在每个Component
内?
这最终会导致一些奇怪的编译器问题,因为Component
包含Container
的头文件,反之亦然。即使使用了头文件修复程序,我最终还是必须在class Component;
标头上声明原型Container
,同样适用于Component
。
在两个类之间进行双向交互似乎需要经历一些麻烦。是否可以寻找另一个解决共同依赖“解决”问题的解决方案,或者是C ++预期的这种错综复杂的实现?我应该把它搞砸了?
编辑:也许某些背景/推理会有所帮助。我使用这种共同依赖的原因是因为我需要在调用子的析构函数时通知父级(因此可以从子级列表中删除它),并且我还需要具有子级的绘制位置相对于父母的。
谢谢,
Jengerer
答案 0 :(得分:2)
通常最好不要有这样的循环依赖:它们对代码来说有点痛苦,对代码,可测试性等的逻辑推理感到沮丧。
无论如何都可以轻松避免它们 - 你可以在组件中保留一些仿函数,然后将它们指向适合于正在处理的事件的Container操作,或者从抽象接口派生Container,这样组件就可以有一个指向它和容器从中派生出来。或者可以通过(智能)指针存储组件,其中派生类型实现为容器定制的虚拟事件处理程序。还有很多其他可能性,例如如果要避免运行时开销,请考虑CRTP或模板策略类。
答案 1 :(得分:2)
实际上我认为这是一个设计问题。你真的应该看看整个设计,看看你是否可以更好地设计它。问问自己为什么你有依赖类需要访问容器。也许容器提供的功能不应该。可以用另一种方式提供此功能吗?
答案 2 :(得分:2)
让一个组件保持指向其父级的指针被广泛使用,我不认为它是不好的做法。它可以用于各种各样的事情,从处理小部件树到处理丢失或泄漏的组件。
要解决编译器的问题,您需要将包含行放在标题保护中,或者让第三个文件具有两个类的前向声明(在相应的命名空间中)。
我已经看到后者在一些大型OO库中完成,然后通常包含在项目中的几乎所有其他文件中。虽然这可能会导致一些名称空间污染,但它有一些好处(不需要包含完整的类定义或另一个类的依赖项,只是为了指向它)。
Widget.hpp:
#include "Library.hpp"
namespace MyLibrary
{
class Widget
{
private:
Window * parent;
};
}
Window.hpp:
#include "Library.hpp"
namespace MyLibrary
{
class Window
{
private:
std::vector<Widget*> widgets;
};
}
Library.hpp:
namespace MyLibrary
{
class Window;
class Widget;
}