与指针的组成

Composition with a pointer

我在使用 RobotControl class 成员时遇到问题。 UML 将 RobotControl 的位置和 RangeSensor 之间的关系指定为组合。不为它们使用指针,使它们聚合?我应该如何声明-根据UML创建这些成员,还是UML弄错了?

C++ 中的指针可用于聚合和组合。正如 所言,区别在于 object 的生命周期是否相互关联。换句话说:当 parent 被销毁时 child 是否被销毁?答案代表组合,代表聚合。

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

C++ 中的指针可以表示另一个(动态创建的)object 的所有权,或者仅指其他人拥有的 object。让我们展示示例中的差异。我将解释为什么指针对每种类型的关系都有用。

用指针聚合

这种情况下,在class Parent声明前只forward-declareclass Child就可以了,child成员可以设置,re-set声明时Parent.

的生命周期
class Child;

class Parent
{
public:
    Parent(Child* ch) : child(ch) {}
    Parent() : child(NULL) {}
    void setChild(Child* ch) { child = ch; }
private:
    Child* child;
};

用指针组合

最长的示例表明我们可以使用指针动态创建和销毁 childchild 的生命周期与 Parent 密切相关。但是,由于指针,我们仍然可以在 Parent 的生命周期内交换 children。与下面的替代方案不同,此解决方案还只允许在头文件中使用 forward-declare class Child

// --- header file
class Child;

class Parent
{
public:
    Parent();
    ~Parent();
    void renewChild();
private:
    Child* child;
};

// --- source file
#include "child.h"

Parent::Parent()
    : child(new Child)
{
}

Parent::~Parent()
{
    delete child;
}

void Parent::renewChild()
{
    delete child;
    child = new Child;
}

免责声明

此示例是 Rule of three/five/zero 的主题。我有意让用户执行缺少的推荐方法,保持这个答案 dialect-agnostic 并尽可能简单。

没有指针的组合

无需手动编写构造函数和析构函数,您只需在class 声明中声明child,让编译器为您完成构造和析构。只要 class Child 的构造函数不需要参数(否则你需要手动编写 class Parent 的构造函数)并且 class Child 在声明class Parent.

#include "child.h"

class Parent
{
private:
    Child child;
};

没有指针的聚合

总而言之,使用指针进行聚合的替代方法是使用引用。但是,这可以防止在 Parent object.

的生命周期内交换 children
class Child;

class Parent
{
public:
    Parent(Child& ch) : child(ch) {}
private:
    Child& child;
};