我在C++中有以下类:
class a { const int b[2]; // other stuff follows // and here's the constructor a(void); }
问题是,如何在初始化列表中初始化b,因为我无法在构造函数体内初始化它,因为b是const
?
这不起作用:
a::a(void) : b([2,3]) { // other initialization stuff }
编辑:这个例子就是我可以b
为不同的实例设置不同的值,但是已知这些值在实例的生命周期内是不变的.
使用C++ 11,这个问题的答案现在已经改变了,你实际上可以做到:
struct a { const int b[2]; // other bits follow // and here's the constructor a(); }; a::a() : b{2,3} { // other constructor work } int main() { a a; }
像其他人说的那样,ISO C++不支持这一点.但你可以解决它.只需使用std :: vector.
int* a = new int[N]; // fill a class C { const std::vectorv; public: C():v(a, a+N) {} };
目前的标准是不可能的.我相信你能够做到这一点的C++ 0x使用初始化列表(见在的C++ 0x略看,由Bjarne Stroustrup的,有关初始化列表和其他不错的C++ 0x功能的更多信息).
std::vector
使用堆.Geez,这只是为了进行const
理智检查而浪费的东西.重点std::vector
是运行时的动态增长,而不是应该在编译时进行的任何旧的语法检查.如果你不想增长,那么创建一个类来包装一个普通的数组.
#includetemplate class ConstFixedSizeArrayFiller { private: size_t length; public: ConstFixedSizeArrayFiller() : length(0) { } virtual ~ConstFixedSizeArrayFiller() { } virtual void Fill(Type *array) = 0; protected: void add_element(Type *array, const Type & element) { if(length >= MaxLength) { // todo: throw more appropriate out-of-bounds exception throw 0; } array[length] = element; length++; } }; template class ConstFixedSizeArray { private: Type array[Length]; public: explicit ConstFixedSizeArray( ConstFixedSizeArrayFiller & filler ) { filler.Fill(array); } const Type *Array() const { return array; } size_t ArrayLength() const { return Length; } }; class a { private: class b_filler : public ConstFixedSizeArrayFiller { public: virtual ~b_filler() { } virtual void Fill(int *array) { add_element(array, 87); add_element(array, 96); } }; const ConstFixedSizeArray b; public: a(void) : b(b_filler()) { } void print_items() { size_t i; for(i = 0; i < b.ArrayLength(); i++) { printf("%d\n", b.Array()[i]); } } }; int main() { a x; x.print_items(); return 0; }
ConstFixedSizeArrayFiller
并且ConstFixedSizeArray
可以重复使用.
第一个允许在初始化数组时进行运行时边界检查(与向量相同),稍后可以const
在此初始化之后进行.
第二个允许将数组分配到另一个对象中,该对象可以在堆上,或者只是堆栈(如果该对象所在的位置).从堆中分配时不浪费时间.它还对数组执行编译时const检查.
b_filler
是一个提供初始化值的微小私有类.使用模板参数在编译时检查数组的大小,因此不可能超出范围.
我敢肯定有更多奇特的方法可以修改它.这是一个初步的刺.我认为你几乎可以弥补任何编译器的类缺点.
ISO标准C++不允许您这样做.如果是这样,语法可能是:
a::a(void) : b({2,3}) { // other initialization stuff }
或类似的规定.从你的问题来看,它实际上听起来像你想要的是一个常数类(又名静态)成员,即数组.C++确实允许你这样做.像这样:
#includeclass A { public: A(); static const int a[2]; }; const int A::a[2] = {0, 1}; A::A() { } int main (int argc, char * const argv[]) { std::cout << "A::a => " << A::a[0] << ", " << A::a[1] << "\n"; return 0; }
输出是:
A::a => 0, 1
当然,因为这是一个静态类成员,它对于类A的每个实例都是相同的.如果那不是你想要的,即你希望A的每个实例在数组中都有不同的元素值,那么你就是在做尝试使数组const开始的错误.你应该这样做:
#includeclass A { public: A(); int a[2]; }; A::A() { a[0] = 9; // or some calculation a[1] = 10; // or some calculation } int main (int argc, char * const argv[]) { A v; std::cout << "v.a => " << v.a[0] << ", " << v.a[1] << "\n"; return 0; }