C++ 初始化模板C+中常量的常量数组+;班

C++ 初始化模板C+中常量的常量数组+;班,c++,templates,initialization,static-members,const-pointer,C++,Templates,Initialization,Static Members,Const Pointer,我想创建一个模板类InitConst,其中一些成员是T的数组。我想在类的对象初始化期间填充这些数组,然后确保这些数组不再更改,因此我为每个这样的数组定义了一个成员const T*const v(我知道第一个常量指元素,第二个常量指指针) 对此进行的实验使我得出结论,将“v”定义为“const指针指向const”,迫使我在最终使用该数组的地址初始化“v”之前分配并填充相应的数组。此外,由于我无法在类“InitConst”的构造函数体内部初始化“v”,因此我得出结论,我需要一个辅助函数,其作用是(a

我想创建一个
模板类InitConst
,其中一些成员是
T
的数组。我想在类的对象初始化期间填充这些数组,然后确保这些数组不再更改,因此我为每个这样的数组定义了一个成员
const T*const v
(我知道第一个常量指元素,第二个常量指指针)

对此进行的实验使我得出结论,将“v”定义为“const指针指向const”,迫使我在最终使用该数组的地址初始化“v”之前分配并填充相应的数组。此外,由于我无法在类“InitConst”的构造函数体内部初始化“v”,因此我得出结论,我需要一个辅助函数,其作用是(a)获取构造函数参数,(b)分配和填充数组,以及(c)使用一些静态指针来保存这些数组的地址。构造函数最终将使用这些静态指针来初始化常量指针,因此我得到了如下代码:

template <typename T>
class InitConst
  {
  public:
  const T* const v1;
  const T* const v2;
  const T* const v3;

  InitConst(T a1, T a2, T a3, int n)
    : v1( init(a1,a2,a3,n) ), v2(init_p.temp_v2), v3(init_p.temp_v3)
    { }

  private:
  struct Tinit {
    T* temp_v1;
    T* temp_v2;
    T* temp_v3;
    };
  static Tinit init_p;

  T* init (T a1, T a2, T a3, int n)
    {
    init_p.temp_v1 = new T[n];
    init_p.temp_v2 = new T[n];
    init_p.temp_v3 = new T[n];
    // populate "temp_v1", "temp_v2" and "temp_v3" using the method's arguments.
    return init_p.temp_v1;
    } // End method init.
  }; // End class InitConst.

template <typename T>
typename InitConst<T>::Tinit InitConst<T>::init_p;
模板
类InitConst
{
公众:
常数T*常数v1;
常数T*常数v2;
常数T*常数v3;
初始常数(T a1,T a2,T a3,int n)
:v1(初始(a1,a2,a3,n)),v2(初始温度v2),v3(初始温度v3)
{ }
私人:
结构物{
T*temp_v1;
T*temp_v2;
T*temp_v3;
};
静态Tinit初始值;
T*init(T a1,T a2,T a3,int n)
{
初始温度v1=新T[n];
初始温度v2=新的T[n];
初始温度v3=新的T[n];
//使用方法的参数填充“temp_v1”、“temp_v2”和“temp_v3”。
返回初始温度v1;
}//结束方法init。
}; // 结束类InitConst。
模板
typename InitConst::Tinit InitConst::init\u p;
<>这个代码按照预期编译和运行,但是我认为这个设计是扭曲的:我习惯于简单的代码,在这里我首先分配一个数组,然后计算它的元素(这两个事情通常发生在构造函数的主体中),然后使用数组。与此相反,构造函数本身几乎什么也不做:它的角色被转移到方法“init”,该方法实际创建数组,并使用一些辅助指针将它们传回构造函数

template <typename T>
class InitConst
{
public:
    const T* const v1;
    const T* const v2;
    const T* const v3;

    InitConst(T a1, T a2, T a3, int n)
        : v1( new T[n] ), v2( new T[n] ), v3( new T[n] )
    {
        T* t1 = const_cast<T*>(v1);
        T* t2 = const_cast<T*>(v2);
        T* t3 = const_cast<T*>(v3);

        //  do intialization here
    }
};
我想知道:

a) 如果我决定将每个指针声明为“const-pointer-to-const”,那么这种设计(或类似的设计)是必要的,还是有一种更干净的方法

b) 将每个指针声明为“const pointer to const”是防止类被误用的一种方法,但也许我不需要这么多。一种稍微不那么严格的方法是将“v1”及其同级声明为私有成员,这样就不能从类外更改它们。但是,这样做也会防止从类外读取它们,我不希望每个数组“vx”都有一个“read_vx”方法。那么我能做些什么呢,也就是说,什么样的方法可以产生更可读的代码,并且至少保证数组不能从类外部更改

提前谢谢,很抱歉写了这么长的文章


编辑:正如我在下面所评论的,在我的实际代码中,我想要计算的各种数组一起计算效率要高得多,这就是我使用单个“init”函数的原因。我在示例中提供的“init”(“a1”、“a2”、“a3”)的参数实际上是误导性的。

根据对您问题的更新,您仍然可以干净地处理初始化,并比我之前建议的进一步减少代码。因为您知道数据是可写的,所以可以使用
const\u cast
并在构造函数中进行初始化

template <typename T>
class InitConst
{
public:
    const T* const v1;
    const T* const v2;
    const T* const v3;

    InitConst(T a1, T a2, T a3, int n)
        : v1( new T[n] ), v2( new T[n] ), v3( new T[n] )
    {
        T* t1 = const_cast<T*>(v1);
        T* t2 = const_cast<T*>(v2);
        T* t3 = const_cast<T*>(v3);

        //  do intialization here
    }
};

不需要
struct Tinit

tempalate<typename T>
InitConst::InitConst(T a1, T a2, T a3, int n)
  : v1(init(a1,n)), v2(init(a2,n)), v3(init(a3,n))
{}

tempalate<typename T>
T* InitConst::init (T a, int n)
{
  T* result = new T[n];
  // TODO: populate result using a
  return result
};

// TODO implement destructor, copy constuctor and
// copy assignement operator
tempalate
InitConst::InitConst(t1,t2,ta3,int n)
:v1(init(a1,n)),v2(init(a2,n)),v3(init(a3,n))
{}
坦帕拉特
T*InitConst::init(ta,int n)
{
T*结果=新的T[n];
//TODO:使用
返回结果
};
//TODO实现析构函数、复制构造函数和
//副本分配运算符

这可能更适合CodeReview。对我来说,更好的设计是避免使用裸指针和STL类型。哦,谢谢:我不知道CodeReview,但我将来会用它来回答类似的问题。这个问题似乎离题了,因为它是关于首先检查软件设计的,谢谢你的回答。现在,事实上,我真正的代码充满了依赖关系(我以前没有提到):虽然我可以单独计算所有数组,但它们一起计算效率要高得多,所以我用一个方法计算所有数组。但是关于“static”和“init”的提示确实适用,再次感谢!如果您可以更新您的问题以包含有关依赖关系的信息,那么就有可能提供可用的解决方案。只需做一份概述DEP的附录。非常感谢,@obvlious船长!
const_cast
非常强大,即使在我的真实代码的其他需求(我在示例中没有提到)的情况下,它也足够了。事实上,它是如此强大,以至于我现在意识到
const
关键字并没有我想象的那么强大。强大的力量带来了……你明白了。只要确保你明智地使用它;)