Team LiB
Previous Section Next Section

15.7. Containers and Inheritance

15.7. 容器与继承

We'd like to use containers (or built-in arrays) to hold objects that are related by inheritance. However, the fact that objects are not polymorphic (Section 15.3.1, p. 577) affects how we can use containers with types in an inheritance hierarchy.

我们希望使用容器(或内置数组)保存因继承而相关联的对象。但是,对象不是多态的(第 15.3.1 节),这一事实对将容器用于继承层次中的类型有影响。

As an example, our bookstore application would probably have the notion of a basket that represents the books a customer is buying. We'd like to be able to store the purchases in a multiset (Section 10.5, p. 375). To define the multiset, we must specify the type of the objects that the container will hold. When we put an object in a container, the element is copied (Section 9.3.3, p. 318).

例如,书店应用程序中可能有购物篮,购物篮代表顾客正在购买的书。我们希望能够在 multiset第 10.5 节)中存储储购买物,要定义 multiset,必须指定容器将保存的对象的类型。将对象放进容器时,复制元素(第 9.3.3 节)。

If we define the multiset to hold objects of the base type

如果定义 multiset 保存基类类型的对象:

     multiset<Item_base> basket;
     Item_base base;
     Bulk_item bulk;
     basket.insert(base);  // ok: add copy of base to basket
     basket.insert(bulk);  // ok: but bulk sliced down to its base part

then when we add objects that are of the derived type, only the base portion of the object is stored in the container. Remember, when we copy a derived object to a base object, the derived object is sliced down (Section 15.3.1, p. 577).

则加入派生类型的对象时,只将对象的基类部分保存在容器中。记住,将派生类对象复制到基类对象时,派生类对象将被切掉(第 15.3.1 节)。

The elements in the container are Item_base objects. Regardless of whether the element was made as a copy of a Bulk_item object, when we calculate the net_price of an element the element would be priced without a discount. Once the object is put into the multiset, it is no longer a derived object.

容器中的元素是 Item_base 对象,无论元素是否作为 Bulk_item 对象的副本而建立,当计算元素的 net_price 时,元素将按不打折定价。一旦对象放入了 multiset,它就不再是派生类对象了。

Because derived objects are "sliced down" when assigned to a base object, containers and types related by inheritance do not mix well.


We cannot fix this problem by defining the container to hold derived objects. In this case, we couldn't put objects of Item_base into the containerthere is no standard conversion from base to derived type. We could explicitly cast a base-type object into a derived and add the resulting object to the container. However, if we did so, disaster would strike when we tried to use such an element. In this case, the element would be treated as if it were a derived object, but the members of the derived part would be uninitialized.

不能通过定义容器保存派生类对象来解决这个问题。在这种情况下,不能将 Item_base 对象放入容器——没有从基类类型到派生类型的标准转换。可以显式地将基类对象强制转换为派生类对象并将结果对象加入容器,但是,如果这样做,当试图使用这样的元素时,会产生大问题:在这种情况下,元素可以当作派生类对象对待,但派生类部分的成员将是未初始化的。

The only viable alternative would be to use the container to hold pointers to our objects. This strategy worksbut at the cost of pushing onto our users the problem of managing the objects and pointers. The user must ensure that the objects pointed to stay around for as long as the container. If the objects are dynamically allocated, then the user must ensure that they are properly freed when the container goes away. The next section presents a better and more common solution to this problem.


Exercises Section 15.7

Exercise 15.28:

Define a vector to hold objects of type Item_base and copy a number of objects of type Bulk_item into the vector. Iterate over the vector and generate the net_price for the elements in the container.

定义一个 vector 保存 Item_base 类型的对象,并将一些 Bulk_item 类型对象复制的到 vector 中。遍历并计算容器中元素的总和。

Exercise 15.29:

Repeat your program, but this time store pointers to objects of type Item_base. Compare the resulting sum.

重复程序,但这次存储 Item_base 类型对象的指针。比较结果总和。

Exercise 15.30:

Explain any discrepancy in the amount generated by the previous two programs. If there is no discrepancy, explain why there isn't one.


Team LiB
Previous Section Next Section