When we need a container that holds objects related by inheritance, we typically define the container to hold pointers (preferably smart pointers (§12.1, p. 450)) to the base class. As usual, the dynamic type of the object to which those pointers point might be the base-class type or a type derived from that base:
vector<shared_ptr<Quote>> basket;
basket.push_back(make_shared<Quote>("0-201-82470-1", 50));
basket.push_back(
make_shared<Bulk_quote>("0-201-54848-8", 50, 10, .25));
// calls the version defined by Quote; prints 562.5, i.e., 15 * $50 less the discount
cout << basket.back()->net_price(15) << endl;
Because basket
holds shared_ptr
s, we must dereference the value returned by basket.back()
to get the object on which to run net_price
. We do so by using ->
in the call to net_price
. As usual, the version of net_price
that is called depends on the dynamic type of the object to which that pointer points.
It is worth noting that we defined basket
as shared_ptr<Quote>
, yet in the second push_back
we passed a shared_ptr
to a Bulk_quote
object. Just as we can convert an ordinary pointer to a derived type to a pointer to an base-class type (§15.2.2, p. 597), we can also convert a smart pointer to a derived type to a smart pointer to an base-class type. Thus, make_shared<Bulk_quote>
returns a shared_ptr<Bulk_quote>
object, which is converted to shared_ptr<Quote>
when we call push_back
. As a result, despite appearances, all of the elements of basket
have the same type.
Exercise 15.28: Define a vector
to hold Quote
objects but put Bulk_quote
objects into that vector
. Compute the total net_price
of all the elements in the vector
.
Exercise 15.29: Repeat your program, but this time store shared_ptr
s to objects of type Quote
. Explain any discrepancy in the sum generated by the this version and the previous program. If there is no discrepancy, explain why there isn’t one.