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

6
如果我理解正确,我们至少有两种不同的实现组合的方式。(为简单起见,排除使用智能指针的实现情况。我几乎不使用STL,也没有学习的欲望。)
让我们来看看维基百科上的示例
class Car
{
  private:
    Carburetor* itsCarb;
  public:   
    Car() {itsCarb=new Carburetor();}
    virtual ~Car() {delete itsCarb;}
};

因此,这是一种方式 - 我们将对象指针作为私有成员。 可以将其重写为以下形式:

class Car
{
  private:
    Carburetor itsCarb;
};

在这种情况下,我们有一个对象本身作为私有成员。(顺便问一句,从术语角度来看,我称这个实体为对象是正确的吗?)
在第二种情况下,不必隐式调用默认构造函数(如果需要调用非默认构造函数,可以在初始化列表中进行),也不必调用析构函数。但这并不是一个大问题...
当然,在某些方面,这两种情况有更明显的差异。例如,在第二种情况下,禁止从Car类的const方法中调用Carburetor实例的非const方法...
是否有“规则”来决定使用哪种方法?我有什么遗漏吗?

1
我认为你的意思是“在Car类的const方法中调用Carburetor实例的非const方法是被禁止的”。 - Laurence Gonsalves
8
“我没有学习STL的愿望。”什么?忽略STL会让你错过C++的一个重要部分。 - rlbond
6
不考虑智能指针的简洁性是自相矛盾的。不想学习STL就像是不想学好C++一样。“标准”中的“S”是标准的一部分。 - Martin York
2
如果你不使用std::string,就会有“血流成河”的场面。 - ChrisW
1
@ rlbond,Martin,ChrisW,Paul:我忘了提到(这是我的错),我不是专业程序员。而且我只是为了一个非常小的跨平台GUI项目使用C++(更好地说,尝试使用)。我选择了Qt,这个框架提供的功能已经足够了。 - Wildcat
显示剩余2条评论
5个回答

9
在这种情况下,我们将对象本身作为私有成员。(顺便说一句,从术语上讲,称这个实体为对象是正确的吗?)
是的,您可以说是类的“对象”或“实例”。
您还可以谈论通过值而不是指针包含数据成员(因为“按指针”和“按值”是谈论传递参数的正常方式,因此我希望人们能理解这些术语被应用于数据成员)。
有什么“规则”可以决定使用哪一个吗?我错过了什么吗?
如果实例由多个容器共享,则每个容器都应该通过指针而不是值来包含它;例如,如果雇员有一个老板实例,则如果几个雇员实例共享同一个老板,则通过指针包括老板。
如果数据成员的生命周期与容器的生命周期不同,则通过指针包括它:例如,如果数据成员在容器之后实例化,或在容器之前销毁,或在容器的生命周期内被销毁并重新创建,或者如果数据成员为空是有意义的。
必须通过指针(或引用)而不是通过值包含数据成员的另一个时机是当数据成员的类型是抽象基类时。
通过指针包括的另一个原因是,这可能允许您更改数据成员的实现,而无需重新编译容器。例如,如果Car和Carburetor在两个不同的DLL中定义,您可能希望通过指针包含Carburetor:因为然后您可以通过安装不同的Carburetor.dll来更改Carburetor的实现,而无需重新构建Car.dll

+1 对于提及参考资料,因为它们似乎迄今被忽视了 - Glen

8

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


2
两种情况不一样。正如nicolascormier所指出的,您可以使用前向声明来避免包含头文件。也许在点踩之前您应该先理解答案。 - Tom Dalling

3

组合:尽可能使用成员变量。当需要多态性或使用前向声明时,请使用指针。当然,在没有智能指针的情况下,使用指针时需要手动进行内存管理。


1
如果 Carb 的生命周期和 Car 相同,那么我认为非指针形式更好。如果你必须替换 Car 中的 Carb,则我会选择指针版本。

0
通常,非指针版本更易于使用和维护。
但在某些情况下,您无法使用它。例如,如果汽车有多个化油器,并且您希望将它们放入数组中,并且化油器构造函数需要参数:您需要通过new创建它们,因此将它们存储为指针。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接