我在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
的不同值,但是已知这些值在实例的生命周期内是恒定的。
答案 0 :(得分:72)
使用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;
}
答案 1 :(得分:32)
与其他人一样,ISO C ++不支持这一点。但你可以解决它。只需使用std :: vector。
int* a = new int[N];
// fill a
class C {
const std::vector<int> v;
public:
C():v(a, a+N) {}
};
答案 2 :(得分:25)
目前的标准是不可能的。我相信你可以使用初始化程序列表在C ++ 0x中执行此操作(有关初始化程序列表和其他不错的C ++ 0x功能的详细信息,请参阅Bjarne Stroustrup的A Brief Look at C++0x)。
答案 3 :(得分:12)
std::vector
使用堆。 Geez,这只是为了const
理智检查而浪费的东西。 std::vector
的要点是在运行时的动态增长,而不是任何应该在编译时完成的旧语法检查。如果你不想增长,那么创建一个类来包装一个普通的数组。
#include <stdio.h>
template <class Type, size_t MaxLength>
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 Type, size_t Length>
class ConstFixedSizeArray {
private:
Type array[Length];
public:
explicit ConstFixedSizeArray(
ConstFixedSizeArrayFiller<Type, Length> & filler
) {
filler.Fill(array);
}
const Type *Array() const {
return array;
}
size_t ArrayLength() const {
return Length;
}
};
class a {
private:
class b_filler : public ConstFixedSizeArrayFiller<int, 2> {
public:
virtual ~b_filler() {
}
virtual void Fill(int *array) {
add_element(array, 87);
add_element(array, 96);
}
};
const ConstFixedSizeArray<int, 2> 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
。
第二个允许将数组分配给 in 另一个对象,该对象可以在堆上,也可以只是堆栈(如果该对象所在的位置)。从堆中分配时不浪费时间。它还对数组执行编译时const检查。
b_filler
是一个提供初始化值的小型私有类。使用模板参数在编译时检查数组的大小,因此不可能超出范围。
我确信有更多奇特的方法来修改它。这是一个初步的刺。我认为你几乎可以弥补编译器中任何类的缺点。
答案 4 :(得分:9)
ISO标准C ++不允许您这样做。如果是这样,语法可能是:
a::a(void) :
b({2,3})
{
// other initialization stuff
}
或者那些东西。从你的问题来看,它实际上听起来像你想要的是一个常数类(又名静态)成员,即数组。 C ++确实允许你这样做。像这样:
#include <iostream>
class 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开始的错误。你应该这样做:
#include <iostream>
class 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;
}
答案 5 :(得分:4)
答案 6 :(得分:4)
我有一个常量数组,它总是以静态方式完成。如果你能接受,那么这段代码应该编译并运行。
#include <stdio.h>
#include <stdlib.h>
class a {
static const int b[2];
public:
a(void) {
for(int i = 0; i < 2; i++) {
printf("b[%d] = [%d]\n", i, b[i]);
}
}
};
const int a::b[2] = { 4, 2 };
int main(int argc, char **argv)
{
a foo;
return 0;
}
答案 7 :(得分:3)
不使用std::vector
堆的解决方案是使用boost::array
,但不能直接在构造函数中初始化数组成员。
#include <boost/array.hpp>
const boost::array<int, 2> aa={ { 2, 3} };
class A {
const boost::array<int, 2> b;
A():b(aa){};
};
答案 8 :(得分:3)
如何通过访问器函数模拟const数组?它是非静态的(如您所请求的),并且它不需要stl或任何其他库:
class a {
int privateB[2];
public:
a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; }
int b(const int idx) { return privateB[idx]; }
}
因为:: privateB是私有的,它在::之外实际上是常量,并且你可以像数组一样访问它,例如。
a aobj(2,3); // initialize "constant array" b[]
n = aobj.b(1); // read b[1] (write impossible from here)
如果您愿意使用一对类,您还可以保护privateB免受成员函数的影响。这可以通过继承;但我想我更喜欢John Harrison's comp.lang.c++ post using a const class.
答案 9 :(得分:2)
readonly DateTime a = DateTime.Now;
我同意,如果你有一个const预定义数组,你也可以将它静态化。 那时你可以使用这个有趣的语法:
//in header file
class a{
static const int SIZE;
static const char array[][10];
};
//in cpp file:
const int a::SIZE = 5;
const char array[SIZE][10] = {"hello", "cruel","world","goodbye", "!"};
然而,我没有找到绕过常数'10'的方法。原因很清楚,它需要知道如何访问数组。一个可能的替代方法是使用#define,但我不喜欢这个方法,而且我不喜欢标题末尾的#undef,并在CPP上编辑注释以防万一发生变化。