3

作为 C++ 程序员,我学到的一个重要且基本的规则是组合优先于继承 ( http://en.wikipedia.org/wiki/Composition_over_inheritance )。

我完全同意这条规则,它使事情比我们使用继承要简单得多。

我有一个应该使用 Composition 解决的问题,但我真的很难做到这一点。

假设您有一台 Vendor Machine,并且您有两种类型的产品:

  1. 离散产品 - 像零食。
  2. 流体产品 - 如饮料。

这两种类型的产品需要在一个名为 VendorCell 的类中表示,该类包含单元格内容。

这两种产品共享一些相同的属性(dm),如价格、数量等......也包含一些不同的属性。

因此,在此处使用 Composition 可能会导致以下结果:

class VendorCell {
private : // default access modifier
    int price;
    int quantity;

    // int firstProductAttributeOnly
    // char secondProductAttributeOnly
};

如您所见,注释行表明,对于单个 VendorCell 取决于它包含的产品,这两个注释行中只有一个是重要且可用的(另一行仅与其他类型相关 - 例如流体)。

因此,我可能有一个 VendorCell,里面有零食,并且不需要它的 secondProductAttributeOnly。

组合(对于 VendorCell)是正确的解决方案吗?对你们来说,有人会通过构造函数来确定 VendorCell 类型,而一个 DM(专用于另一种类型的 DM)根本不会被使用(例如,将其标记为 -1),这对你们来说是否合适?>

谢谢大家!

4

2 回答 2

4

您赞成组合而不是继承的一般规则是正确的。这里的问题是你想要一个多态对象的容器,而不是一个可以容纳所有可能产品的巨大聚合类。但是,由于切片问题,您不能直接保存多态对象,而是需要通过(最好是智能)指针来保存它们。您可以通过(智能)指针直接持有它们,例如

class AbstractProduct { /* price, quauntity interface */ };
class AbstractSnack: public AbstractProduct { /* extended interface */ };
class AbstractDrink: public AbstractProduct { /* extended interface */ };
typedef std::unique_ptr<AbstractProduct> VendorCell;
typedef std::vector< VendorCell > VendorMachine;

您只需从 AbstractSnack/AbstractDrink 派生来定义您的零食/饮料

class SnickersBar: public AbstractSnack { /* your implementation */ };
class CocaColaBottle: public AbstractDrink { /* your implementation */ };

然后您可以像这样插入或提取产品:

// fill the machine
VendorMachine my_machine;
my_machine.emplace_back(new SnickersBar());
my_machine.emplace_back(new CocaColaBottle());

my_snack = my_machine[0]; // get a Snickers bar
my_drink = my_machine[1]; // get a Coca Cola bottle;

还有其他解决方案,例如Boost.Any,它使用内部保存指向多态对象的指针的包装类。您还可以通过将 替换为typedef包含 a 的单独类VendorMachine来重构此代码std::vector< VendorCell >,以便您可以获得更好的界面(例如具有货币兑换功能)

于 2013-01-28T09:29:30.457 回答
0

你继承是为了被重用。

您编写以便重用。

如果你有不同的属性,那么你可能想要继承,否则组合。

一些变化:

class ProductVariety {
public:
    virtual void display(Screen& screen) = 0;
};

一个实现:

class Liquid : public ProductVariety {
public:
    virtual void display(Screen& screen) {
        //...
    }
}

作曲变奏:

class Product
{
    int price;
    int quantity;

    unique_ptr<ProductVariety> variety;
}
于 2013-01-28T09:36:14.450 回答