与指针的组合

ali*_*mir 6 c++ oop pointers composition

类的 UML 图

\n\n

我在使用 RobotControl 类成员时遇到问题。UML 将 RobotControl\xe2\x80\x99s 位置和 RangeSensor 之间的关系指定为组合。不为它们使用指针,使它们聚合吗?我应该如何声明 - 根据 UML 创建这些成员,或者 UML 是否错误?

\n

Mel*_*ius 5

C++ 中的指针可用于聚合和组合。正如Douglas 正确指出的那样,区别在于对象的生命周期是否相互关联。换句话说:当父进程被销毁时,子进程是否也被销毁?答案“Yes”代表组合,“No”代表聚合。

\n\n

我们如何在 C++ 代码中区分这些情况?

\n\n

C++ 中的指针可以表示另一个(动态创建的)对象的所有权,或者仅引用其他人拥有的对象。让\xe2\x80\x99s 显示示例中的差异。我\xe2\x80\x99 将解释为什么指针对于每种类型的关系都很有用。

\n\n

用指针聚合

\n\n

在这种情况下,最好只前向声明class Childbeforeclass Parent声明,并且child可以在 的生命周期内设置和重新设置成员Parent

\n\n
class Child;\n\nclass Parent\n{\npublic:\n    Parent(Child* ch) : child(ch) {}\n    Parent() : child(NULL) {}\n    void setChild(Child* ch) { child = ch; }\nprivate:\n    Child* child;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

与指针的组合

\n\n

最长的例子表明我们可以child使用指针动态创建和销毁。\xe2\x80\x99s 生命周期childParent. 然而,由于指针的存在,我们仍然可以child在生命周期内交换 ren 。Parent与下面的替代方案不同,该解决方案还允许仅class Child在头文件中进行前向声明。

\n\n
// --- header file\nclass Child;\n\nclass Parent\n{\npublic:\n    Parent();\n    ~Parent();\n    void renewChild();\nprivate:\n    Child* child;\n};\n\n// --- source file\n#include "child.h"\n\nParent::Parent()\n    : child(new Child)\n{\n}\n\nParent::~Parent()\n{\n    delete child;\n}\n\nvoid Parent::renewChild()\n{\n    delete child;\n    child = new Child;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

免责声明

\n\n

此示例遵循三/五/零规则。我故意让用户来实现缺少的推荐方法,使​​这个答案与方言无关并且尽可能简单。

\n\n

没有指针的组合

\n\n

您无需手动编写构造函数和析构函数,只需child在类声明中进行声明,然后让编译器为您完成构造和析构。只要class Child\xe2\x80\x99s 构造函数不需要参数(否则你\xe2\x80\x99d 需要手动编写class Parent\xe2\x80\x99s 构造函数)并且class Child在 的声明之前完全声明,这就是有效的class Parent

\n\n
#include "child.h"\n\nclass Parent\n{\nprivate:\n    Child child;\n};\n
Run Code Online (Sandbox Code Playgroud)\n\n

没有指针的聚合

\n\n

为了完整起见,使用指针进行聚合的替代方法是使用引用。child但是,这会阻止在对象的生命周期内交换ren Parent

\n\n
class Child;\n\nclass Parent\n{\npublic:\n    Parent(Child& ch) : child(ch) {}\nprivate:\n    Child& child;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

  • 这个答案中严重缺乏智能指针和 3/5/0 规则。 (5认同)
  • 好吧,除了避免问题之外,智能指针还有一个明显的优势:如果你看到一个 `std::unique_ptr` 成员,你几乎可以肯定你处于“与指针组合”的情况。它会自动完成这一切*并且*用一行表达您的意图。很难称之为“额外的复杂性”:p (3认同)