我想创建一个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的常量指针”,或者有更简洁的方法可以实现,那么这个设计(或类似的东西)是否必要?
b)将每个指针声明为“指向const的const指针”是一种防止类错误的方法,但也许我不需要那么多。一种稍微不那么严格的方法是将“v1”及其兄弟姐妹声明为私人成员,这样他们就无法从课堂外改变。但是,这样做也会阻止它们从类外部读取,我不希望每个数组“vx”都有一个“read_vx”方法。然后我可以做些什么,也就是说,什么方法会导致代码更易读,并且仍然保证至少不能从类外部更改数组?
提前致谢,并为长篇散文感到抱歉。
编辑:正如我在下面评论的那样,在我的实际代码中,我想要计算的各种数组一起被更有效地计算,这就是我使用单个“init”函数的原因。我在示例中提供的“init”(“a1”,“a2”,“a3”)的参数实际上是误导性的。
答案 0 :(得分: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
使用的每个类型的T
定义InitConst
变量。您还可以将init
更改为 static ,以防止意外使用尚未初始化的成员变量。
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
}
};
答案 1 :(得分:0)
不需要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