В моей программе я столкнулся с другой трудностью (я храню их все и задаю много проблем в пачках: P). У меня есть функтор - все эти функторы наследуются от DuplicateFn
- у него есть виртуальный оператор (), и каждый дочерний элемент должен написать свою версию этого.
Теперь один из дочерних объектов - называемый слиянием - может не сработать, и в этом случае ему следует попробовать запасной метод. В настоящее время этот класс выглядит так:
class MergeFn : public DuplicateFn {
public:
MergeFn() : FallBack(new SkipFn())
{
}
MergeFn(GMProject const* Out, GMProject const* In, DuplicateFn* f)
: DuplicateFn(Out, In), FallBack(f)
{
}
virtual void operator() (GMProject::pTree& tOut, const GMProject::pTree& tIn) const {
if (!GMProject::isMergeable(tOut.GetName())) {
(*FallBack)(tOut, tIn); //virtual table resolves this to the correct class
} else {
}
}
private:
std::shared_ptr<DuplicateFn> FallBack;
};
Я думаю, что проблема ясно видна уже здесь - в конструкторе не по умолчанию этот метод захватывает владение данным параметром. - Это не то, что я хочу: он должен скопировать этот параметр и сохранить его в собственности.
Теперь я попробовал , FallBack(new DuplicateFn(f))
Однако это тоже не сработает - поскольку теперь возникает ошибка компиляции, когда он пытается создать экземпляр объекта из класса с помощью чисто виртуальных методов.
Так как я могу это сделать? - Нужно ли указывать конкретный конструктор для каждого типа? - Просто чтобы скопировать это? Или я должен пройти через RTTI? Я надеюсь, что есть лучший подход, чем эти 2.
редактировать
Чтобы показать, как mergeFn инициализируется (и используется):
std::unique_ptr<detail::DuplicateFn> foo;
foo.reset(new detail::MergeFn(this, &Other, DuplicateFns.at(HandleDuplicate)));
DuplicateFns - это карта, которая помогает преобразовывать пользовательские входные данные (строки) в указатели функций. - Или как сейчас, указатели на объекты подтипа из DuplicateFn (тип указателя - DuplicateFn *)
Затем используется как метод обратного вызова.
ProjectTree.combine_if(tree, &SimilarTreeValue, foo.get());
, который объединяет 2 дерева в одно - когда SimilarTreeValue возвращает true, запись считается дубликатом. Если запись является листом, то вызывается третий параметр - функтор, о котором мы говорим:).