Мое первое знакомство с C ++ - это создание библиотеки синтеза звука (EZPlug).
Библиотека разработана для того, чтобы упростить настройку графика взаимосвязанных объектов генератора звука и процессора.Мы можем вызвать EZPlugGenerators
Все процессорные модули могут принимать один или несколько EZPlugGenerators в качестве входных данных.
Для меня важно, чтобы все методы конфигурации этих EZPlugGenerators были цепными.Другими словами, методы, используемые при настройке графа синтеза, должны всегда возвращать указатель на родительский объект.Это позволяет мне использовать синтаксис, который очень хорошо показывает вложенную природу отношений объекта, как это:
mixer.addGenerator(
a(new Panner())
->setVolume(0.1)
->setSource(
a(new TriggererPeriodic())
->setFrequency(
v(new FixedValue(1), "envTriggerFreq")
)
->setTriggerable(
a(new Enveloper())
->setAllTimes(v(0.0001), v(0.05), v(0.0f, "envSustain"), v(0.01))
->setAudioSource(
a(new SineWaveMod())
->setFrequency(
a(new Adder())
->addGenerator(a(new Adder()))
->addGenerator(v(5000, "sineFreq"))
->addGenerator(
a(new Multiplier())
->addVal(v("sineFreq"))
->addVal(
a(new TriggererPeriodic())
->setFrequency(v("envTriggerFreq"))
->setTriggerable(
a(new Enveloper())
->setAllTimes(0.1, 0.1, 0, 0.0001)
->setAudioSource(v(1, "envAmount"))
)
)
)
)
)
)
)
);
Функции "a" и "v" в приведенном выше хранилище кода и возвращают ссылкик объектам и обрабатывать их извлечение и уничтожение.
Я подозреваю, что мой подход к C ++ выглядит немного странно, но я обнаружил, что язык действительно может приспособить способ, которым я хочу программировать довольно хорошо.
Теперь на мой вопрос
Я хотел бы создать общий суперкласс для всех генераторов EZPlugGenerator, которые могут принимать входные данные для наследования.Этот суперкласс будет иметь метод "addInput", который будет переопределен каждым подклассом.Проблема заключается в том, что я хочу, чтобы addInput возвращал указатель на экземпляр подкласса, а не суперкласс.
Это недопустимо:
EZPlugProcessor* addInput(EZPlugGenerator* generator)
, потому что это возвращает указатель на экземпляр суперкласса, а не на подкласс, разрушающий цепочечность, которой я так доволен.
Я пробовал это:
template<typename T> virtual T* addInput(EZPlugGenerator* obj){
, но компилятор говорит мне, что я не могу создать функцию виртуального шаблона.
У меня нет необходимости использовать наследование здесь.Я могу реализовать addInput на каждом EZPlugGenerator, который может принимать входные данные.Похоже, что объединение их всех в один родительский класс поможет понять, что у них всех есть что-то общее, и поможет закрепить тот факт, что addInput
является правильным способом подключения одного объекта к другому.
Итак, есть ли способ, которым я могу использовать наследование, чтобы диктовать, что каждый член группы классов должен реализовывать метод addInput, в то же время позволяя этому методу возвращать указатель на экземпляр дочернего класса?