C++ Primer 学习笔记_70_面向对象编程 --纯虚函数、容器与继承(二)

2014-11-24 12:52:56 · 作者: · 浏览: 26
关联的对象。但是,对象不是多态的,这一事实对将容器用于继承层次中的类型有影响。

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

    multiset
  
    basket;
    Item_base base;
    Bulk_item bulk;

    basket.insert(base);    //OK
    basket.insert(bulk);    //OK:但是,bulk的派生类部分将被无情的“切割”掉

  

则加入派生类型的对象时,只将对象的基类部分保存在容器中。谨记:将派生类对象复制到基类对象时,派生类对象将被切掉。因此,一旦放入了multiset,他就不再是派生类对象了。

【小心地雷】

因为派生类对象在赋值给基类对象时会被“切掉”,所以容器与通过继承相关的类型不能很好的融合。

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

唯一可行的选择可能是使用容器保存对象的指针。这个策略可行,但代价是需要用户面对管理对象和指针的问题,用户必须保证只要容器存在,被指向的对象就存在。如果对象是动态分配的,用户必须保证在容器消失时适当地释放对象。

//P504 习题15.28
int main()
{
    vector
  
    itemVec;
    for (size_t i = 0; i != 10; ++i)
    {
        Bulk_item item("C++ Primer",6,5,0.5);
        itemVec.push_back(item);
    }

    double sum = 0;
    for (vector
   
    ::iterator iter = itemVec.begin(); iter != itemVec.end(); ++iter) { sum += iter -> net_price(10); //调用Item_base:: net_price } cout << sum << endl; //output 600 } 
   
  

//习题15.29
int main()
{
    vector
  
    itemVec;
    for (size_t i = 0; i != 10; ++i)
    {
        Bulk_item *item = new Bulk_item("C++ Primer",6,5,0.5);
        itemVec.push_back(item);
    }

    double sum = 0;
    for (vector
   
    ::iterator iter = itemVec.begin(); iter != itemVec.end(); ++iter) { sum += (*iter) -> net_price(10); } cout << sum << endl; //output 300 //显式释放动态分配的内存 for (vector
    
     ::iterator iter = itemVec.begin(); iter != itemVec.end(); ++iter) { delete *iter; } }