禁止虚拟模板功能的解决方法
workaround for prohibition on virtual template functions?
我对C++的第一次尝试是构建一个音频合成库(EZPlug)。
该库的设计目的是便于设置互连音频生成器和处理器对象的图形。我们可以将EZPlugGenerators称为
所有处理器单元都可以接受一个或多个EZPlugGenerator作为输入。
对我来说,这些EZPlugGenerator上的所有配置方法都是可链接的,这一点很重要。换句话说,用于设置合成图的方法应该始终返回指向父对象的指针。这允许我使用一种语法,它非常好地显示了对象关系的嵌套性质,如下所示:
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"answers"v"函数存储并返回对对象的引用,并处理检索和销毁它们
我怀疑我的C++方法看起来有点奇怪,但我发现这种语言实际上可以很好地适应我想要的编程方式。
现在回答我的问题
我想为所有EZPlugGenerator创建一个通用的超类,它可以接受要继承的输入。这个超类将有一个方法"addInput",它将被每个子类覆盖。问题来自于这样一个事实:我希望"addInput"返回一个指向子类实例的指针,而不是超类。
这是不可接受的:
EZPlugProcessor* addInput(EZPlugGenerator* generator)
因为这会返回一个指向超类实例的指针,而不是破坏我非常满意的可链接性的子层。
我试过这个:
template<typename T> virtual T* addInput(EZPlugGenerator* obj){
但编译器告诉我不能创建一个虚拟模板函数。
我不必在这里使用继承。我可以在每一个可以接受输入的EZPlugGenerator上实现"addInput"。看起来,将所有这些对象聚集在一个单亲类下将有助于明确它们都有共同点,并有助于强化addInput
是将一个对象插入另一个对象的正确方法这一事实。
那么,有没有一种方法可以使用继承来规定一组类的每个成员都必须实现"addInput"方法,同时允许该方法返回指向子类实例的指针?
C++中的虚拟函数可以具有协变返回类型,这意味着您可以定义
virtual EZPlugProcessor *addInput(EZPlugGenerator* generator) = 0;
在基类中,然后是
struct MyProcessor : EZPlugProcessor {
virtual MyProcessor *addinput(EZPlugGenerator* generator) {
...
return this;
}
};
只要调用者知道(通过他们使用的类型)对象是MyProcessor
,他们就可以将addInput
与MyProcessor
特定的其他函数链接在一起。
如果你的继承层次结构有更多的层次,那么不幸的是,你有时会发现自己在写:
struct MySpecificProcessor : MyProcessor {
virtual MySpecificProcessor *addinput(EZPlugGenerator* generator) {
return static_cast<MySpecificProcessor*>(MyProcessor::addInput(generator));
}
};
因为无法在EZPlugProcessor
中指定addInput
的返回类型为"指向对象的最派生类型的指针"。每个派生类都必须为自己"激活"协方差。
class Base
{
public:
virtual Base* add() = 0 { return <some base ptr>; }
};
class Child : public Base
{
public:
virtual Child* add() { return <some child ptr>; }
};
另一方面,没有人能够读取您的代码,因此您可能需要考虑是否有其他方法可以设置配置,而不是用C++编写LISP链接。
- 有没有办法在 c++ 中同时生成随机数?如果没有,是否有解决方法?
- 从 int 中剥离位时,编译器会警告一个转换,但不警告其他转换.有解决方法吗?
- 是否有解决方法可以在 c++ 中为 short 定义用户定义的文字?
- 不为 emplace() 定义构造函数的解决方法
- 删除复制构造函数的 Intel 13.1.2 中不良C++行为的解决方法
- 函数模板部分专业化-有什么解决方法吗
- 带boost的过载模糊性:可选,解决方法
- 继承构造函数和其他变量的解决方法
- C++ 解决方法:"从类型"B*"的表达式初始化类型"C*&"的引用无效"
- 对前向声明类型进行unique_ptr的解决方法
- 解决方法:'can not be used when making a shared object; recompile with -fPIC'使用Cmake。使用普通的 g++ 工作
- 解决方法:QPixmap:在GUI线程之外使用pixmap是不安全的
- CreateProcessWithTokenW 的 cmdline 参数的最大长度是否有解决方法?
- C++双精度作为模板参数的解决方法
- 在参数相关查找之前进行模板替换的任何方法(或解决方法?
- CUDA 内核"Only a single pack parameter is allowed"解决方法?
- dlsym() 解决方法返回类型
- VS2017是否有VLA(可变长度阵列)支持解决方法
- 解决方法:未定义对"class::function"的引用
- 来自 Boost 的 JSON 解析器的警告 C4512 的解决方法