tl; dr - Состав кажется правильным выбором для моей ситуации, но я бы хотел избежать накладных расходов на распределение кучи для каждого объекта, который я собираю вместе. Какие-нибудь хорошие методы?Избегайте дополнительных распределений кучи с композицией (над наследованием)?
У меня есть установка, которая выглядит как:
class Foo {
public:
Foo(unique_ptr<FooEvaluator> evaluator)
: evaluator_(std::move(evaluator)),
common_state_() {}
void FooMethod() {
// Perform some common processing.
evaluator.DoSomething();
}
private:
unique_ptr<FooEvaluator> evaluator_;
Bar common_state_;
}
class FooEvaluator {
public:
virtual void DoSomething() = 0;
}
class FooEvaluatorImpl : public FooEvaluator {
public:
FooEvaluatorImpl(type1 arg) {...}
void DoSomething() override {...}
}
class FooEvaluatorImplVariant : public FooEvaluator {
public:
FooEvaluatorImplVariant(type2 arg) {...}
void DoSomething() override {...}
}
Грубо: У меня есть Foo, который делает некоторые общие обработки, а затем использует FooEvaluator. У меня есть несколько реализаций FooEvaluator, каждая из которых имеет свою логику. Обычная обработка Foo достаточно нетривиальна, что имеет смысл попытаться избежать ее дублирования.
Я обеспокоен тем, что теперь я должен выделить два объекта вместо одного, если бы у меня был монолитный Foo, содержащий как общую логику, так и логику оценки.
Одно смутно разумное промежуточное поле, о котором я могу думать, это унаследовать FooEvaluator от Foo и добавить DoSomething()
в качестве частного виртуального метода на Foo. Это немного злоупотребление наследованием imo (вы не можете сказать, что FooEvaluator "является" Foo), но он получит мой общий код и избежит выделения двойной памяти.
Любые мысли?
все имеют примерно такой же размер Foo оценщика? Если это так, я бы превратил их в вариант std :: variant или boost: variant и имел функцию посетителя, которая реализует то, что обычно является интерфейсом виртуальных функций. – RyanP
Можете ли вы заменить виртуальное наследование на crtp, т. Е. Составить композицию во время компиляции? Это убивает уникальные_ptr, распределения кучи и vtables в обмен на потерю стирания типа (или перемещение его на уровень). –
Я не уверен, что вы подразумеваете под «композицией»? Можете ли вы привести пример? Я не понимаю, как состав может привести к множественным распределениям. (Наверное, мое собственное невежество!) –