我作为C ++程序员学到的一个重要而重要的规则是组合优先于继承(http://en.wikipedia.org/wiki/Composition_over_inheritance)。
我完全赞同这个规则,这个规则主要使事情比我们使用继承更简单。
我有一个问题应该使用Composition来解决,但我真的很难这样做。
假设您有 供应商计算机 ,并且您有两种类型的产品:
这两类产品需要在名为VendorCell的类中表示,该类包含单元格内容。
这两种产品共享一些相同的属性(dm),如价格,数量等...... 但也包含一些不同的属性。
因此,在此处使用Composition可能会产生以下结果:
class VendorCell {
private : // default access modifier
int price;
int quantity;
// int firstProductAttributeOnly
// char secondProductAttributeOnly
};
正如您所看到的,注释行显示对于单个VendorCell,取决于包含的产品,这两条注释行中只有一行是重要且可用的(另一条仅与另一种类型 - 例如流体。)
因此,我可能有一个里面装有零食的VendorCell,不需要它的第二个产品属性。</ p>
组合(对于VendorCell)是否是正确的解决方案?对于你们来说,有人会通过构造函数确定VendorCell类型并且一个DM(专用于其他类型的DM)将不会被使用(例如将其标记为-1)吗?&gt;
谢谢大家!
答案 0 :(得分:4)
你偏爱继承的一般规则是正确的。这里的问题是你想要一个container of polymorphic objects,而不是一个可以容纳所有可能产品的巨型聚合类。但是,由于slicing problem,您无法直接保存多态对象,但需要通过(最好是智能)指针来保存它们。您可以通过(智能)指针直接按住它们,例如
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
替换为包含VendorMachine
的单独的类std::vector< VendorCell >
来重构此代码,以便您可以获得更好的界面(具有货币兑换功能,例如)
答案 1 :(得分: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;
}