C++ - это язык с несколькими парадигмами. Он светит ярче и является самым мощным, когда парадигмы смешиваются.
class Property
{
public:
Property(const std::string& name) //note: we don't lightly copy strings in C++
: m_name(name) {}
virtual ~Property() {}
private:
std::string m_name;
};
template< typename T >
class TypedProperty : public Property
{
public:
TypedProperty (const std::string& name, const T& data)
: Property(name), m_data(data);
private:
T m_data;
};
typedef std::vector< std::shared_ptr<Property> > property_list_type;
Edit: Почему с помощью std::shared_ptr<Property>
вместо Property*
?
Рассмотрим этот код:
void f()
{
std::vector<Property*> my_property_list;
for(unsigned int u=0; u<10; ++u)
my_property_list.push_back(new Property(u));
use_property_list(my_property_list);
for(std::vector<Property*>::iterator it=my_property_list.begin();
it!=my_property_list.end(); ++it)
delete *it;
}
Это for
цикл там пытается очистки, удаляя все свойства в векторе, только прежде чем она выходит из области видимости и принимает все указатели с ним.
Теперь, хотя это может показаться хорошим для новичков, если вы только слегка опытный разработчик на C++, этот код должен поднять тревожные звонки, как только вы посмотрите на него.
Проблема заключается в том, что вызов use_property_list()
может вызвать исключение. Если это так, функция f()
будет оставлена сразу. Для правильной очистки будут вызваны деструкторы для всех автоматических объектов, созданных в f()
. То есть, my_property_list
будет правильно уничтожен. Затем деструктор std::vector
будет хорошо очищать данные, которые он хранит.Однако он содержит указатели, и как должно std::vector
знать, являются ли эти указатели последними, ссылающимися на их объекты?
Поскольку он не знает, он не удалит объекты, он уничтожит указатели только тогда, когда он уничтожит его содержимое, оставив вас с объектами в куче, в которых у вас больше нет указателей. Это то, что называется «утечкой».
Чтобы избежать этого, вам нужно будет поймать все исключения, очистить свойства и сбросить исключение. Но затем, через десять лет, кто-то должен добавить новую функцию к приложению 10MLoC, к которому это выросло, и, будучи в спешке, добавляет код, который преждевременно покидает эту функцию, когда выполняется какое-либо условие. Код протестирован, и он работает и не разбивается - только сервер, в котором он сейчас находится, теперь просачивается несколько байтов в час, что приводит к его сбою из-за нехватки памяти примерно раз в неделю. Обнаружение, которое делает для многих часов штраф отладки.
Нижняя строка: никогда не управляйте ресурсами вручную, всегда обертывайте их в объекты класса, предназначенные для обработки только одного экземпляра такого ресурса. Для динамически выделенных объектов эти ручки называются «умный указатель», а наиболее используемый - shared_ptr
.
Аналогично тому, как вы хотите использовать Boost.Variant: http://stackoverflow.com/questions/1358427/function-which-returns-an-unknown-type – AraK
Boost - это не вариант. – hasdf
Ваши классы 'PropertyXxxx' должны наследовать от' class Property'. Вы можете отредактировать свой пост. –