2013-06-25 5 views
0

У меня есть некоторые фундаментальные проблемы для понимания поведения хранения производных объектов в контейнере базового типа в C++.Хранение полученного объекта в контейнере базового типа

Может ли кто-нибудь объяснить вывод нижеследующего кода? Я думал, что поведение должно быть одинаковым в обеих функциях.

// Output 
test_func1 
UseCount: 1 
UseCount: 2 
test_func2 
UseCount: 1 
UseCount: 1 // Why??? 
class base_class 
{ 
public: 
    base_class() { } 
    virtual ~base_class() { } 
}; 

class derived_class : public base_class 
{ 
public: 
    derived_class(const std::shared_ptr<int>& i) 
     : base_class(), 
      i_(i) 
    { } 

    ~derived_class() { } 

private: 
    std::shared_ptr<int> i_; 
}; 

void test_func1() 
{ 
    std::cout << "test_func1" << std::endl; 
    std::vector<derived_class> v; 
    std::shared_ptr<int> i(new int(100)); 
    std::cout << "UseCount: " << i.use_count() << std::endl; 
    v.push_back(derived_class(i)); 
    std::cout << "UseCount: " << i.use_count() << std::endl; 
} 

void test_func2() 
{ 
    std::cout << "test_func2" << std::endl; 
    std::vector<base_class> v; 
    std::shared_ptr<int> i(new int(100)); 
    std::cout << "UseCount: " << i.use_count() << std::endl; 
    v.push_back(derived_class(i)); 
    std::cout << "UseCount: " << i.use_count() << std::endl; 
} 

int main(int argc, char *argv[]) 
{ 
    test_func1(); 
    test_func2(); 
    return 0; 
} 
+1

Читайте на [обрезке объектов] (http://en.wikipedia.org/wiki/Object_slicing). – juanchopanza

+0

Спасибо. Это мой первый раз услышать этот термин ... – alex

ответ

0

Потому что во втором случае ваш базовый класс копия возведенных из производного класса, переданного push_back метода. И ваш базовый класс не хранит shared_ptr<int>. Вы получили экземпляр класса, который был уничтожен после возврата push_back.

void test_func2() 
{ 
    std::cout << "test_func2" << std::endl; 
    std::vector<base_class> v; 
    std::shared_ptr<int> i(new int(100)); //use count is 1 
    std::cout << "UseCount: " << i.use_count() << std::endl; 
    v.push_back(derived_class(i)); //base_class is copy constructed here and store in v 
    //derived_class() is destroyed ans use count is still 1 
    std::cout << "UseCount: " << i.use_count() << std::endl; 
} 
1

Вы не можете хранить полученные объекты в станд :: вектор базового класса. Попытайтесь это запомнить.

Этот вектор хранит базовый класс, больше ничего. В push_back производные части срезаются.

Если вы хотите иметь полиморфную коллекцию, посмотрите, как это сделать, «полиморфная коллекция STL» - хороший запрос либо на SO, либо вообще.

+0

Спасибо. Так глупо я. – alex