如果我理解正确,我们至少有两种不同的方式来实现合成。 (为简单起见,排除了使用智能指针实现的情况。我几乎不使用STL,也不希望学习它。)

让我们来看看Wikipedia example:

class Car
{
  private:
    Carburetor* itsCarb;
  public:
    Car() {itsCarb=new Carburetor();}
    virtual ~Car() {delete itsCarb;}
};

因此,这是一种方法-我们有一个指针将对象作为私有(private)成员。
可以将其重写为如下形式:
class Car
{
  private:
    Carburetor itsCarb;
};

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

在第二种情况下,没有必要隐式调用默认构造函数(如果需要调用非默认构造函数,则可以在初始值设定项列表中进行调用)和析构函数。但这不是大问题...

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

是否有任何“规则”来决定使用哪个?我想念什么吗?

最佳答案



是的,您可以说出该类的“对象”或“实例”。

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



如果实例由多个容器共享,则每个容器都应通过指针而不是值来包含该实例;例如,如果一个雇员有一个老板实例,如果几个雇员实例共享同一个老板,则按指针包括老板。

如果数据成员的生存期与容器的生存期不同,则通过指针将其包括在内:例如,数据成员是在容器之后实例化的,还是在容器之前被销毁的,或者在容器中被销毁并重新创建的容器的生存期,或者数据成员为null是否有意义。

另一个必须通过指针(或通过引用)而不是按值包括的时间是,数据成员的类型是抽象基类。

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

07-25 23:04