Поскольку вы явно заявляете, что хотите улучшить свой C ++, я рекомендую вам начать использовать Boost . Это может помочь вам решить вашу проблему тремя различными способами:
Использование shared_ptr
Использование shared_ptr
может объявить ваш вектор следующим образом:
std::vector< boost::shared_ptr< ObjectBase > > object_list;
И используйте это так:
typedef std::vector< boost::shared_ptr< ObjectBase > >::iterator ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
(*it)->draw(view);
Это даст вам полиморфизм и будет использоваться точно так же, как и обычный вектор указателей, но shared_ptr
будет выполнять управление памятью за вас, уничтожая объект, когда последний shared_ptr
ссылающийся на него будет уничтожен.
Примечание о C ++ 11: В C ++ 11 shared_ptr
стало частью стандарта как std::shared_ptr
, поэтому Boost больше не требуется для этого подхода. Однако, если вам действительно не нужно совместное владение, рекомендуется использовать std::unique_ptr
, который был недавно представлен в C ++ 11.
Использование ptr_vector
Используя ptr_vector
, вы сделаете это так:
boost::ptr_vector< ObjectBase > object_list;
И используйте это так:
typedef boost::ptr_vector< ObjectBase >::iterator ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
(*it)->draw(view);
Это снова будет использоваться как обычный вектор указателей, но на этот раз ptr_vector
управляет временем жизни ваших объектов. Отличие от первого подхода состоит в том, что здесь ваши объекты уничтожаются при разрушении вектора, тогда как выше они могут жить дольше контейнера, если существуют другие shared_ptr
ссылки на них.
Использование reference_wrapper
Используя reference_wrapper
, вы объявите это следующим образом:
std::vector< boost::reference_wrapper< ObjectBase > > object_list;
А потом используйте это так:
typedef std::vector< boost::reference_wrapper< ObjectBase > >::iterator
ObjectIterator;
for ( ObjectIterator it = object_list.begin(); it != object_list.end(); it++ )
it->draw(view);
Обратите внимание, что вам не нужно сначала разыменовывать итератор, как в описанных выше подходах. Однако это работает, только если время жизни ваших объектов управляется в другом месте и гарантированно будет больше, чем у vector
.
Примечание о C ++ 11: reference_wrapper
также стандартизировано в C ++ 11 и теперь может использоваться как std::reference_wrapper
без Boost.
Как указано в ответе Maciej H , ваш первый подход приводит к срезанию объекта . В общем случае при использовании контейнеров вы можете захотеть взглянуть на итераторов .