【问题标题】:virtual functions with a non-void return type具有非 void 返回类型的虚函数
【发布时间】: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/…
  • 编译器无法确定GHighPrecisionTapProcessing 对象的一个​​实例。例如,如果GStepPrecisionTapProcessing 的一个实例,那么您希望G-&gt;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


【解决方案1】:

问题出在这几行...

      virtual uint getTapIndex(uint index) {};
      virtual uint getTapIndexLow(uint index) {};
      virtual uint getTapIndexHigh(uint index) {};

他们描述了一个返回uint的函数,提供了一个实现,但实际上并不返回一个值。

如果有一个合理的基础实现,那么最好提供它。但是在这里,您似乎想要一个pure virtual 方法,使您的课程成为abstract。您希望所有派生类都实现一个值。例如

      virtual uint getTapIndex(uint index) =0;  // require derived classes to implement
      virtual uint getTapIndexLow(uint index) { return 0 } // can be overridden, but defaults to returning zero.
      virtual uint getTapIndexHigh(uint index) = 0; // require derived classes to implement.

【讨论】:

  • 所以问题是我不想在 StepPrecisionTapProcessing 中实现 getTapIndexHigh 和 getTapIndexLow 以及在 HighPrecisionTapProcessing 中实现 getTapIndex,因为它们不属于那里。使它们成为纯虚拟将迫使我在两个类中实现所有三个方法,这在这种情况下有点违背多态性的目的。
猜你喜欢
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 2017-02-08
  • 1970-01-01
  • 2013-07-05
相关资源
最近更新 更多