C ++:关联,聚合和组合 [英] C++ : Association, Aggregation and Composition

查看:155
本文介绍了C ++:关联,聚合和组合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我开始研究OOAD,并且很难找到C++代码示例,该示例说明了如何以编程方式实现AssociationAggregationComposition. (到处都有几篇文章,但它们与C#或Java有关).我确实找到了一个或两个示例,但是它们都与我的讲师的说明相抵触,我感到困惑.

I'm beginning to study OOAD and I'm having difficulty finding a C++ code example that'd illustrate how Association, Aggregation and Composition are implemented programmatically. (There are several posts everywhere but they relate to C# or java). I did find an example or two, but they all conflict with my instructor's instructions and I'm confused.

我的理解是:

  • 关联:Foo拥有一个指向Bar对象作为数据成员的指针
  • 聚集:Foo有一个指向Bar对象的指针,并且Bar的数据被深复制到该指针中.
  • 组成:Foo有一个Bar对象作为数据成员.
  • Association: Foo has a pointer to Bar object as a data member
  • Aggregation: Foo has a pointer to Bar object and data of Bar is deep copied in that pointer.
  • Composition: Foo has a Bar object as data member.

这就是我的实现方式:

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

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


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

这是正确的吗?如果没有,那么应该怎么做呢?如果您还给我提供了一本书中代码的参考(以便我可以与我的老师讨论),将不胜感激

Is this correct? If not, then how should it be done instead? It'd be appreciated if you also give me a reference of a code from a book (so that I can discuss with my instructor)

推荐答案

我将忽略聚合.它不是一个非常明确定义的概念, ,在我看来,这引起了更多的混乱,而不是值得的.组成和关联就足够了, Craig Larman 告诉我.这可能不是您的老师想要的答案,但是无论如何,它都不可能以C ++的方式与Association有所不同.

I'm going to ignore Aggregation. It is not a very clearly defined concept and in my opinion it causes more confusion than it is worth. Composition and Association are quite enough, Craig Larman told me so. It might not be the answer your instructor was looking for but it is unlikely to be implemented in C++ any differently to Association anyway.

没有一种实现组合和关联"的方法.如何实现它们取决于您的要求,例如关系的多重性.

There is not one way of implementing Composition and Association. How you implement them will depend on your requirements, for example the multiplicity of the relationship.

实现合成的最简单方法是使用一个简单的Bar成员变量,就像您建议的那样.我唯一要做的更改是初始化构造函数成员初始化器列表中的bar:

The simplest way of implementing composition is using a simple Bar member variable much like you suggested. The only change I would make is to initialize the bar in the constructor member initializer list:

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

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

It is generally a good idea to initialize member variables using the constructor initialization list, it can be quicker and in some cases like const member variables it is the only way to initialize them.

也可能有使用指针实现合成的原因.例如,Bar可能是多态类型,而您在编译时不知道具体类型.或者,您可能希望转发声明Bar以最大程度地减少编译依赖性(请参阅 PIMPL习惯用法).或这种关系的多重性可能是1到0..1,并且您需要能够有一个空的Bar.当然,因为这是Composition Foo应该拥有Bar,并且在C ++ 11/C ++ 14的现代世界中,我们更喜欢使用智能指针而不是原始指针:

There might also be a reason to implement composition using a pointer. For example Bar could be a polymorphic type and you don't know the concrete type at compile time. Or perhaps you want to forward declare Bar to minimize compilation dependencies (see PIMPL idiom). Or perhaps the multiplicity of this relationship is 1 to 0..1 and you need to be able to have a null Bar. Of course because this is Composition Foo should own the Bar and in the modern world of C++11/C++14 we prefer to use smart pointers instead of owning raw pointers:

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

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

I've used std::unique_ptr here because Foo is the sole owner of Bar but you might want to use std::shared_ptr if some other object needs a std::weak_ptr to Bar.

通常会使用指针来实现关联:

Association would usually be implemented using a pointer as you have done:

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

当然,您需要确信Bar在使用Foo时将仍然存在,否则您的指针会悬空.如果Bar的生存期不太清楚,则std::weak_ptr可能更合适:

Of course you need to be confident that Bar will be alive while Foo is using it otherwise you have a dangling pointer. If the lifetime of Bar is less clear then a std::weak_ptrmay be more appropriate:

// 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,而不必担心指针悬空:

Now Foo can use the Bar without fear of being left with a dangling pointer:

 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来实现协会,但是我认为这应该是最后的选择.

In some cases where ownership of Bar is really unclear an Association could be implemented using a std::shared_ptr but I think that should be a last resort.

关于使用Bar指针的深层副本进行聚合的实现.我不会说这是典型的实现,但正如我所说,这取决于您的要求. 您确实需要确保在Foo析构函数中的bar成员指针上调用delete,尽管否则会发生内存泄漏(或使用智能指针).

Regarding your implementation of Aggregation with a deep copy of a Bar pointer. I wouldn't have said that was a typical implementation but, as I said, it depends on your requirements. You do need to make sure you call delete on your bar member pointer in the Foo destructor though otherwise you have a memory leak (or use a smart pointer).

这篇关于C ++:关联,聚合和组合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆