Я работаю над личным проектом, чтобы познакомиться с C ++ 11 и Boost.
У меня есть наследственные отношения с UrlExtractor
базовый класс, с TagUrlExtractor
производный класс и CompoundExtractor
производный класс. CompoundExtractor
может содержать любое количество UrlExtractors
, таким образом, реализуя составной шаблон.
Мне любопытно, что подпись метода для CompositeExtractor.addExtractor
должен выглядеть так. Поскольку я имею дело с полиморфным типом, я вынужден работать с указателями (или ссылками). Я хочу использовать новые умные указатели, в частности, shared_ptr
,
Я пытался написать addExtractor
функция-член, как это:
void addExtractor(shared_ptr<UrlExtractor> extractor);
Тем не менее, я получаю ошибку компиляции, если я пытаюсь написать:
compound.addExtractor(new TagUrlExtractor());
Проблема в том, что для создания shared_ptr<UrlExtractor>
: один к UrlExtractor
базовый класс и второй к shared_ptr
,
Я мог бы вызвать функцию так:
compound.addExtractor(shared_ptr<UrlExtractor>(new TagUrlExtractor));
Однако это очень многословно. Как эта ситуация обрабатывается нормально?
Проблема в том, что для создания shared_ptr потребуется два неявных преобразования: одно в базовый класс UrlExtractor, а второе в shared_ptr
Это не проблема: проблема в том, что конструктор shared_ptr
который принимает необработанный указатель помечен как explicit
, поэтому его нельзя использовать в контексте инициализации копирования (параметры функции инициализируются при копировании, как указано в п. 8.5 / 15).
Вы могли (и на самом деле, должны) использовать std::make_shared
:
compound.addExtractor(std::make_shared<TagUrlExtractor>());
std::make_shared()
имеет преимущество быть исключительным а также выполнение одного динамического выделения меньше, чем при инициализации общего указателя из new
выражение (см. также этот вопрос&А на StackOverflow).
Других решений пока нет …