gpt4 book ai didi

C++ : Association, 聚合和组合

转载 作者:IT老高 更新时间:2023-10-28 21:47:51 25 4
gpt4 key购买 nike

我开始研究 OOAD,但我很难找到一个 C++ 代码示例来说明 AssociationAggregation 如何和 Composition 以编程方式实现。 (到处都有几篇文章,但它们与 C# 或 java 有关)。我确实找到了一两个例子,但它们都与我导师的指示相冲突,我很困惑。

我的理解是:

  • 关联: Foo 有一个指向 Bar 对象的指针作为数据成员
  • 聚合: Foo 有一个指向 Bar 对象的指针,并且 Bar 的数据被深度复制到该指针中。
  • 组合: Foo 有一个 Bar 对象作为数据成员。

这就是我实现它的方式:

class Bar
{
Baz baz;
};

//ASSOCIATION (with Bar)
class Foo
{
Bar* bar;
void setBar(Bar* _bar)
{
bar = _bar;
}
};

//AGGREGATION (with Bar)
class Foo
{
Bar* bar;
void setBar(Bar* _bar)
{
bar = new Bar;
bar->baz = _bar->baz;
}
};


//COMPOSTION (with Bar)
class Foo
{
Bar bar;
Foo(Baz baz)
{
bar.baz = baz;
}
};

这是正确的吗?如果没有,那么应该如何做呢?如果您还可以给我引用书中的代码,将不胜感激(以便我可以与我的导师讨论)

最佳答案

我将忽略聚合。是not a very clearly defined concept在我看来,它引起的困惑多于其值(value)。组合和联想就够了,Craig Larman这么告诉我的。这可能不是您的讲师正在寻找的答案,但无论如何它不太可能在 C++ 中与 Association 有任何不同。

没有一种方法可以实现组合和关联。您如何实现它们将取决于您的要求,例如关系的多样性。

作曲

实现组合的最简单方法是使用简单的 Bar成员变量很像你建议的。我要做的唯一更改是初始化 bar在构造函数成员初始化列表中:

// COMPOSITION - with simple member variable
class Foo {
private:
Bar bar;
public:
Foo(int baz) : bar(baz) {}
};

使用构造函数初始化列表来初始化成员变量通常是一个好主意,它可以更快,并且在某些情况下,例如 const 成员变量,它是初始化它们的唯一方法。

使用指针实现组合也可能是有原因的。例如 Bar可能是多态类型,您在编译时不知 Prop 体类型。或者你想转发声明Bar最小化编译依赖(见PIMPL idiom)。或者这种关系的多重性可能是 1 到 0..1,您需要能够有一个空值 Bar .当然因为这是作文Foo应该拥有Bar在 C++11/C++14 的现代世界中,我们更喜欢使用智能指针而不是拥有原始指针:

 // COMPOSITION - with unique_ptr
class Foo {
private:
std::unique_ptr<Bar> bar;
public:
Foo(int baz) : bar(barFactory(baz)) {}
};

我用过std::unique_ptr这里是因为 FooBar 的唯一所有者但您可能想使用 std::shared_ptr如果其他对象需要 std::weak_ptrBar .

联想

关联通常会像您所做的那样使用指针来实现:

// Association - with non-owning raw pointer
class Foo {
private:
Bar* bar;
public:
void setBar(Bar* b) { bar = b; }
};

当然你需要确信Bar将在 Foo 期间还活着正在使用它,否则你有一个悬空指针。如果 Bar 的生命周期不如 std::weak_ptr可能更合适:

// Association - with weak pointer
class Foo {
private:
std::weak_ptr<Bar> bar;
public:
void setBar(std::weak_ptr<Bar> b) { bar = std::move(b); }
void useBar() {
auto b = bar.lock();
if (b)
std::cout << b->baz << "\n";
}
};

现在 Foo可以使用Bar不用担心留下一个悬空的指针:

 Foo foo;
{
auto bar = std::make_shared<Bar>(3);
foo.setBar(bar);
foo.useBar(); // ok
}
foo.useBar(); // bar has gone but it is ok

在某些情况下,Bar 的所有权真的不清楚是否可以使用 std::shared_ptr 来实现关联。但我认为这应该是最后的手段。

关于使用 Bar 的深层拷贝实现聚合指针。我不会说这是一个典型的实现,但正如我所说,这取决于您的要求。 您确实需要确保调用 delete在您的 bar Foo 中的成员指针析构函数,否则您有内存泄漏(或使用智能指针)。

关于C++ : Association, 聚合和组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25779394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com