如何在C++中实现类组合?

Wil*_*cat 6 c++ oop

如果我理解正确,我们至少有两种不同的方法来实现组合.(为了简单起见,使用智能指针实现的情况除外.我几乎不使用STL而且不想学习它.)

我们来看看维基百科的例子:

class Car
{
  private:
    Carburetor* itsCarb;
  public:   
    Car() {itsCarb=new Carburetor();}
    virtual ~Car() {delete itsCarb;}
};
Run Code Online (Sandbox Code Playgroud)

所以,这是一种方式 - 我们有一个指向对象指针作为私有成员.可以将其重写为如下所示:

class Car
{
  private:
    Carburetor itsCarb;
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我们将对象本身作为私有成员.(顺便说一句,从术语的角度来看,我是否正确地称这个实体为对象?)

在第二种情况下,隐式调用默认构造函数(如果需要调用非默认构造函数,可以在初始化列表中执行)和析构函数,则不是必须的.但这不是一个大问题......

当然,在某些方面,这两种情况的区别更为明显.例如,在第二种情况下禁止从Car类的const方法调用Carburetor实例的非const方法...

是否有任何"规则"来决定使用哪一个?我错过了什么吗?

nic*_*ico 8

我倾向于选择第一种情况,因为第二种情况要求你在Car.h中#include Carburettor.h.由于Carburettor是私人会员,因此您不必在其他地方包含其定义,而不是在实际的Car实施代码中.使用Carburettor类显然是一个实现细节,使用Car对象的外部对象不必担心包含其他非强制依赖项.通过使用指针,您只需在Car.h中使用Carburettor的前向声明.

  • 两种情况都不一样.正如nicolascormier所指出的,您可以使用前向声明来避免包含头文件.也许你应该在downvoting之前理解答案. (2认同)

Chr*_*isW 8

在这种情况下,我们将对象本身作为私有成员.(顺便说一句,将这个实体称为对象我是从术语的角度来写的吗?)

是的,你可以说这个类的"对象"或"实例".

您还可以讨论包含数据成员"按值"而不是"按指针"(因为"按指针"和"按值"是谈论传递参数的正常方式,因此我希望人们会理解这些应用的术语数据成员).

是否有任何"规则"来决定使用哪一个?我错过了什么吗?

如果实例由多个容器共享,则每个容器应该通过指针而不是值来包含它; 例如,如果Employee有一个Boss实例,如果多个Employee实例共享同一个Boss,则通过指针包含Boss.

如果数据成员的生命周期与容器的生命周期不同,则通过指针包含它:例如,如果数据成员在容器之后实例化,或在容器之前销毁,或在销毁期间销毁并重新创建容器的生命周期,或者数据成员是否有意义.

另一次必须通过指针(或引用)而不是按值包含数据成员的类型是抽象基类.

包含指针的另一个原因是,这可能允许您在不重新编译容器的情况下更改数据成员的实现.例如,如果Car and Carburetor在两个不同的DLL中定义,您可能希望通过指针包含Carburetor:因为那时您可以通过安装另一个来更改Carburetor的实现Carburetor.dll,而无需重建Car.dll.