1

我想创建一个template <typename T> class InitConst其中一些成员是T. 我想在类的对象初始化期间填充这些数组,然后确保这些数组不会再改变,所以我const T* const v为每个这样的数组定义了一个成员(我知道第一个 const 是指元素,第二个是指针)。

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

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;

这段代码按预期编译和工作,但我认为这个设计是扭曲的:我习惯于简单的代码,我首先分配一个数组,然后计算它的元素(这两件事通常发生在构造函数的主体中),然后使用数组。相比之下,构造函数本身几乎什么都不做:它的角色被转移到方法“init”,它实际上创建了数组并使用一些辅助指针将它们传递回构造函数。

然后我想知道:

a) 如果我决定将每个指针声明为“指向 const 的 const 指针”,这种设计(或类似的东西)是否必要,或者有更简洁的方法来做到这一点?

b) 将每个指针声明为“指向 const 的 const 指针”是一种防止滥用类的方法,但也许我不需要那么多。一种不太严格的方法是将“v1”及其兄弟姐妹声明为私有成员,以便不能从类外部更改它们。但是,这样做也会阻止从类外部读取它们,并且我不希望每个数组“vx”都有一个“read_vx”方法。然后我能做些什么,也就是说,什么方法会导致代码更具可读性,并且至少仍然保证不能从类外部更改数组?

在此先感谢,并为冗长的散文感到抱歉。

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

4

2 回答 2

2

根据对您问题的更新,您仍然可以干净地处理初始化并比我之前建议的进一步减少代码。由于您知道数据是可写的,因此您可以const_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
    }
};



[注意:根据 OP 的评论,以下解决方案不可用]

最好一次init帮助初始化单个成员变量,而不是全部三个。这将显着减少代码并消除对需要为使用的每种类型static定义的变量的需要。您还可以更改为静态,以防止意外使用尚未初始化的成员变量。TInitConstinit

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,n) ), v2( init(a2,n)), v3(init(a3,n))
    { }

private:
    static const T* init (T a, int n)
    {
        T* v = new T[n];
        // populate "v" from "a"
        return v
    }
};
于 2013-05-26T16:09:47.810 回答
1

不需要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
于 2013-05-26T16:11:18.910 回答