i just went through something very similar. really the only thing the cart should know about is the product id and the quantity. everything else should be for display purposes only. in other words the product object is always responsible for the price. the only reason that a price is stored in the cart is to help show it in the view. otherwise we assume that the price always has to be checked with any insert or update, to prevent fraud.
here is another scenario - you have a special on shipping, like buy $100 worth of qualifying goods and you get free shipping. there might be a separate shipping special on specific products. the only way to calculate is with all of the cart items.
so my solution - which i am not sure is optimal - is to pass the cart items to a shipping object - do the shipping calculations - optionally add messaging for specific products to display in the cart - and then return the cart items.
otherwise you are having to put shipping methods in the cart class which does not make any sense but maybe there is another way to do this.
here is another scenario - inventory control. someone orders 30 blue widgets but you only have 10 blue widgets. ok you can check for inventory when you insert item in cart. but what if they update the cart and then increase to 30? that means that we have to check inventory - for every item in the cart - every time the cart is updated. and if we are doing that then might as well get the price in case it has gone up or down.
so i take the cart items - and pass them to a product object - which checks inventory - and if necessary reduces the quantity of the items down to current inventory - optionally adds messaging explaining that stock is limited - then passes back to cart object.
finally - suggest that you have an object that owns the shopping session. and then thats where the totals would be. that way the cart is never in charge of totals - its just a container. one way is you just start an order and then store the different totals there.