【问题标题】:Pass the template typename to the constructor of a nested class将模板类型名传递给嵌套类的构造函数
【发布时间】:2014-07-12 18:28:17
【问题描述】:

我正在编写一个预测校正数值求解器。我已经编写了一个有效的循环数组来跟踪我的函数以前的值。

#include <cmath>
// Circular array
// this is fixed sized container to hold the last n update of a function
// written by Keivan Moradi 2014
template <typename T>
class carray
{
    public:
        carray(int s)
        {
            size = exp2(ceil(log2(s)));
            array =  new T[size];
            SizeNegOne = size-1;
            head = SizeNegOne;
        }
        void initialize(T n)
        {
            for (head=0; head<size; head++)
                array[head]=n;
            head = SizeNegOne;
        }
        void update(T h)
        {
            // bitwise modulus:
            // if "size" is in power of 2:
            //(head+1) & SizeNegOne = (head+1) % size
            // in contrast to modulus, this method is guaranteed to get positive values
            head = (head+1) & SizeNegOne;
            array[head]=h;
        }
        T operator[](int index)
        {
            // bitwise modulus:
            // if "size" is in power of 2:
            // (head + index) & SizeNegOne = (head + index) % size
            // in contrast to modulus, this method is guaranteed to get positive values
            return array[(head + index) & SizeNegOne];
        }
        ~carray()
        {
            delete [] array;
        }
    protected:
    private:
        T *array;
        int size, SizeNegOne, head;
};

以下代码显示了该代码应该如何工作:

int main()
{
    carray<float> phi(3);
    phi.initialize(-64);
    std::cout<<phi[0]<<" "<<phi[-1]<<" "<<phi[-2]<<" "<<phi[-3]<<" "<<phi[-4]<<" "<<phi[-5]<<" "<<phi[-6]<<" "<<phi[-7]<<" "<<phi[-8]<<std::endl<<std::endl;

    phi.update(6.1);
    std::cout<<phi[0]<<" "<<phi[-1]<<" "<<phi[-2]<<" "<<phi[-3]<<" "<<phi[-4]<<" "<<phi[-5]<<" "<<phi[-6]<<" "<<phi[-7]<<" "<<phi[-8]<<std::endl<<std::endl;

    phi.update(7.1);
    std::cout<<phi[0]<<" "<<phi[-1]<<" "<<phi[-2]<<" "<<phi[-3]<<" "<<phi[-4]<<" "<<phi[-5]<<" "<<phi[-6]<<" "<<phi[-7]<<" "<<phi[-8]<<std::endl<<std::endl;

    phi.update(8.1);
    std::cout<<phi[0]<<" "<<phi[-1]<<" "<<phi[-2]<<" "<<phi[-3]<<" "<<phi[-4]<<" "<<phi[-5]<<" "<<phi[-6]<<" "<<phi[-7]<<" "<<phi[-8]<<std::endl<<std::endl;

    phi.update(9.1);
    std::cout<<phi[0]<<" "<<phi[-1]<<" "<<phi[-2]<<" "<<phi[-3]<<" "<<phi[-4]<<" "<<phi[-5]<<" "<<phi[-6]<<" "<<phi[-7]<<" "<<phi[-8]<<std::endl<<std::endl;

    phi.update(10.1);
    std::cout<<phi[0]<<" "<<phi[-1]<<" "<<phi[-2]<<" "<<phi[-3]<<" "<<phi[-4]<<" "<<phi[-5]<<" "<<phi[-6]<<" "<<phi[-7]<<" "<<phi[-8]<<std::endl<<std::endl;

    return 0;
}

现在我想将这个类嵌套在一个预测器类中,这样我就可以像这样使用它:

int main()
{
    predictor<float> phi(4);
    phi.update(10);
    phi.update(11);
    phi.update(12);
    phi.update(13);
    std::cout<<phi.predict2ndOrder()<<std::endl;
}

这段代码显示了我失败的最佳尝试:

#include <cmath>
template <typename T>
class predictor
{
    public:
        predictor(int s)
        {
            size = s;
        }
        void update(T a)
        {
            f.update(a);
        }
        T predict2ndOrder()
        {
            return f[0] + (3/2*(f[0]-f[-1])-1/2*(f[-1]-f[-2]));
        }
    private:
        int size;
        carray<T> f(size);
        class carray
        {
            public:
                carray(int s)
                {
                    size = exp2(ceil(log2(s)));
                    array =  new T[size];
                    SizeNegOne = size-1;
                    head = SizeNegOne;
                }
                ~carray()
                {
                    delete [] array;
                }
                void initialize(T n)
                {
                    for (head=0; head<size; head++)
                        array[head]=n;
                    head = SizeNegOne;
                }
                void update(T h)
                {
                    head = (head+1) & SizeNegOne;
                    array[head]=h;
                }
                T operator[](int index)
                {
                    return array[(head + index) & SizeNegOne];
                }
            private:
                T *array;
                int size, SizeNegOne, head;
        };
};

请告诉我如何解决这个问题?我是一个新的 C++ 程序员,所以请放轻松。 ;)

【问题讨论】:

  • 我注意到你没有关注Rule of Three
  • Rule of Zero 相同
  • 所以使用std::vector
  • 我确实理解了三法则,我可以根据这些规则修复我的代码。但是,我不明白你对零规则的解释。据我所知,std::vector 不是一个循环数组。

标签: c++ class templates constructor nested


【解决方案1】:

示例代码中有一些错别字,我不会介绍,但是将类型 T 从预测器传输到 carray 非常简单。这是一种可能性:像在第一个代码片段中所做的那样,将 carray 声明为模板类。为了使其余工作正常进行,请更正拼写错误,将 size 和 f 的声明移至 carray 和 init size 的类定义下方,并将 f 作为预测器构造函数中的正确顺序的初始化列表。

这是修改后的代码,在 VS2010 中对我来说编译得很好:

#include <cmath>
using namespace std;

template <typename T>
class predictor
{
public:
   predictor(int s)
      : size(s)
      , f(size)
   {
   }
   void update(int a)
   {
      f.update(a);
   }
   T predict2ndOrder(float deltaT)
   {
      return f[0] + deltaT*(3/4*(f[0]-f[1]-1/2*(f[1]-f[2])));
   }
private:
   template <typename S>
   class carray
   {
   public:
      carray(int s)
      {
         size = exp(ceil(log((S)s)));
         array =  new S[size];
         SizeNegOne = size-1;
         head = SizeNegOne;
      }
      ~carray()
      {
         delete [] array;
      }
      void initialize(S n)
      {
         for (head=0; head<size; head++)
            array[head]=n;
         head = SizeNegOne;
      }
      void update(S h)
      {
         head = (head+1) & SizeNegOne;
         array[head]=h;
      }
      S operator[](int index)
      {
         return array[(head + index) & SizeNegOne];
      }
   private:
      S *array;
      int size, SizeNegOne, head;
   };

   int size;
   carray<T> f;
};

【讨论】:

  • 我已经尝试过您建议的代码。我已经修复了拼写错误,但我仍然在 code::blocks: error: declaration of 'class T' error: shadows template parm 'class T' 中收到这些错误。在 Visual Studio 2013 中,没有错误,但也没有输出。我还有一个问题,(T)s 是某种类型的演员吗?如果它是别的东西,它叫什么,以便我可以了解更多关于它的信息。谢谢
  • @user9224 对阴影模板参数感到抱歉;只需将 carray-T-template-param 更改为不同的东西。你对选角是对的;我认为需要选择正确的日志实现,f.e.在 log(float) 和 log(double) 之间。您也可以编写不像 C 而更像 C++ 的 static_cast(s)。关于输出,我承认我根本没有看过语义。我更新了对 carray 的新模板参数名称的答案。
  • @user9224 我从不使用代码块,但运行代码(包括对模板参数名称的建议更改)确实在 VS2010 上给了我一个输出,我看不到任何可能导致空输出;因为 phi.predict2ndOrder 返回一个浮点数,所以总会有一个值打印到 std::cout。另请注意,在您显示的最后一个 main() 中,预测器不会为其名为 array 的数组成员调用 initialise() ;也许你想在预测器构造函数中调用它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-10
  • 1970-01-01
相关资源
最近更新 更多