【发布时间】:2017-06-17 03:14:36
【问题描述】:
考虑以下继承和组合方案。
// 示例程序
#include <iostream>
#include <valarray>
using namespace std;
class TapProcessing
{
public:
TapProcessing(){};
virtual ~TapProcessing(){};
virtual void getWeights(valarray<double> &weights) {};
virtual void getPrecisionWeights (valarray<double> &precWeights) {};
virtual const uint &getTapIndex(const uint index) const
{
valarray<uint> a;
a.resize(10);
return a[index];
}; //const {return 0;};
virtual const uint &getTapIndexLow(const uint index) const
{
valarray<uint> a;
a.resize(10);
return a[index];
}; //const {return 0;};;
virtual const uint &getTapIndexHigh(const uint index) const
{
valarray<uint> a;
a.resize(10);
return a[index];
}; //const {return 0;};
};
class StepPrecisionTapProcessing : public TapProcessing
{
public:
StepPrecisionTapProcessing() { _tapIndex.resize(10, 3); }
~StepPrecisionTapProcessing() {};
void getWeights(valarray<double> &weights) { return weights.resize(10);}
virtual const uint &getTapIndex(const uint index) const {return _tapIndex[index]; }
private:
valarray<uint> _tapIndex;
};
class HighPrecisionTapProcessing : public TapProcessing
{
public:
HighPrecisionTapProcessing()
{
_tapIndexLow.resize(10, 4);
_tapIndexHigh.resize(10, 5);
}
~HighPrecisionTapProcessing() {};
void getPrecisionWeights (valarray<double> &precWeights) { return precWeights.resize(10); };
virtual const uint &getTapIndexLow(const uint index) const {return _tapIndexLow[index]; }
virtual const uint &getTapIndeHigh(const uint index) const {return _tapIndexHigh[index]; }
private:
valarray<uint> _tapIndexLow;
valarray<uint> _tapIndexHigh;
};
class Generator
{
public:
Generator(bool isPrecision)
{
if (isPrecision) {_tp = new HighPrecisionTapProcessing();
}
else { _tp = new StepPrecisionTapProcessing(); }
}
~Generator() { delete _tp; }
const uint &getTapIndex(const uint index) const {return _tp->getTapIndex(index); }
const uint &getTapIndexLow(const uint index) const {return _tp->getTapIndexLow(index); }
const uint &getTapIndexHigh(const uint index) const {return _tp->getTapIndexHigh(index); }
private:
TapProcessing *_tp;
};
int main()
{
Generator *G = new Generator(true);
uint index = 5;
cout<<"High tap index is = "<<G->getTapIndexHigh(index)<<endl;
delete G;
return 0;
}
当我运行 main 时,我得到以下输出,
高点指数 = 0
这里如果派生类中的getTapIndeHigh声明覆盖了基类中的声明,我们会在输出中看到值5而不是0。为什么派生类实现没有覆盖非类方法的基类实现无效的虚拟方法?
【问题讨论】:
-
"是否可以有一个非 void 返回类型的虚函数?"你试过了吗? “我可以给出一个将被派生类 getter 覆盖的虚拟返回值吗?”您似乎对什么是虚函数缺乏一些相当基本的理解。没有“虚拟返回值”这样的东西。它要么是被调用函数的返回值,要么不是。你想要一个纯虚函数吗?那是一个在基类中没有定义的虚函数。 en.wikipedia.org/wiki/…
-
编译器无法确定
G是HighPrecisionTapProcessing对象的一个实例。例如,如果G是StepPrecisionTapProcessing的一个实例,那么您希望G->getTapIndexHigh(index)究竟返回什么?由于没有函数StepPrecisionTapProcessing::getTapIndexHigh(uint)的声明,运行时将调用基本函数TapProcessing::getTapIndexHigh(uint),您没有为其提供带有返回值的定义。编译器需要函数virtual uint TapProcessing::getTapIndexHigh(uint)来返回uint值。 -
您希望生成器实际上包含特定类型的 TapProcessing,但具有通用接口和实现。我不确定你为什么想要那个,但如果这真的是你想要的,那么我会让你的 TapProcesing 基类在它的函数实现中抛出异常(如果编译器仍然抱怨,则在从未执行的返回之前),您的派生类将覆盖它。这样,如果您在底层类型不支持的生成器上调用错误的函数,您将在运行时收到异常,因为您不知道实际的底层类型。
-
如果你走我建议的路线,那么对 Generator 类的需求在很大程度上就消失了——至少在这个例子中是这样。只需使用新的 HighPrecisionTapProcessing 或新的 StepPrecisionProcessing 对象初始化 TapProcessing unique_ptr 即可。哦,你可能也想让 TapProcessing 的析构函数变成虚拟的。
标签: c++ virtual-functions