C++ 在C+;中的类初始值设定项中初始化常量数组+;

C++ 在C+;中的类初始值设定项中初始化常量数组+;,c++,initialization,c++03,array-initialize,C++,Initialization,C++03,Array Initialize,我有以下C++类: class a { const int b[2]; // other stuff follows // and here's the constructor a(void); } 问题是,如果我不能在构造函数的函数体中初始化b,因为b是const,那么如何在初始化列表中初始化b 这不起作用: a::a(void) : b([2,3]) { // other initialization stuff } 编辑:这种情况下

我有以下C++类:

class a {
    const int b[2];
    // other stuff follows

    // and here's the constructor
    a(void);
}
问题是,如果我不能在构造函数的函数体中初始化b,因为b是
const
,那么如何在初始化列表中初始化b

这不起作用:

a::a(void) : 
    b([2,3])
{
     // other initialization stuff
}

编辑:这种情况下,对于不同的实例,我可以为
b
设置不同的值,但已知这些值在实例的生命周期内是恒定的。

您不能从初始化列表中执行此操作

看看这个:


:)

这在当前标准中是不可能的。我相信您可以使用初始值设定项列表在C++0x中实现这一点(有关初始值设定项列表和其他优秀的C++0x特性的更多信息,请参阅Bjarne Stroustrup)。

在我有一个常量数组的地方,它总是作为静态数组来完成的。如果您可以接受这一点,那么应该编译并运行此代码

#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;
}
#包括
#包括
甲级{
静态常数int b[2];
公众:
a(无效){
对于(int i=0;i<2;i++){
printf(“b[%d]=[%d]\n”,i,b[i]);
}
}
};
常数int a::b[2]={4,2};
int main(int argc,字符**argv)
{
阿福;
返回0;
}

< P> 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的每个实例在数组a中有不同的元素值,那么您就犯了一个错误,试图从数组常量开始。你应该这样做:

#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;
}
#包括
甲级
{
公众:
A();
int a[2];
};
A::A()
{
[0]=9;//或某些计算
a[1]=10;//或某些计算
}
int main(int argc,char*const argv[]
{
A v;

STD:像其他人一样,ISO C++不支持这个。但是你可以解决它。只需使用STD::矢量代替。
int* a = new int[N];
// fill a

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};
int*a=新的int[N];
//填补
C类{
常数std::向量v;
公众:
C():v(a,a+N){}
};
有趣的是,在C#中,关键字const转换为C++的静态const,而readonly只能在构造函数和初始化中设置,甚至可以通过非常量设置,例如:

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,但我不喜欢该方法,我在标题的末尾未定义,在CPP处添加注释,以便在发生更改时进行编辑。

std::vector
使用heap.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;
}
#包括
模板
类constFixedSizerAyFiller{
私人:
尺寸与长度;
公众:
ConstFixedSizeArrayFiller():长度(0){
}
虚拟~ConstFixedSizeArrayFiller(){
}
虚拟空隙填充(类型*数组)=0;
受保护的:
void add_元素(类型*数组、常量类型和元素)
{
如果(长度>=最大长度){
//todo:抛出更合适的越界异常
掷0;
}
数组[长度]=元素;
长度++;
}
};
模板
类ConstFixedSizeArray{
私人:
类型数组[长度];
公众:
显式ConstFixedSizeArray(
ConstFixedSizerRayFiller和filler
) {
filler.Fill(数组);
}
常量类型*数组()常量{
返回数组;
}
大小\u t排列长度()常数{
返回长度;
}
};
甲级{
私人:
b类填料:公共ConstFixedSizeArrayFiller{
公众:
虚拟~b_filler(){
}
虚拟空白填充(int*数组){
添加_元素(数组,87);
添加_元素(数组,96);
}
};
const constefixedsizearray b;
公众:
a(空):b(b_filler()){
}
作废打印项目(){
尺寸i;
对于(i=0;i
ConstFixedSizerRayFiller
ConstFixedSizerRay
是可重用的

第一种方法允许在初始化数组时进行运行时边界检查(与向量可能相同),在初始化之后,数组可能会变成
const

第二种方法允许在另一个对象内分配数组,该对象可以位于堆上,也可以位于堆栈上(如果对象位于堆栈上的话)。从堆中分配不会浪费时间。它还对数组执行编译时常量检查

b_filler
是一个很小的私有类,用于提供初始化值。数组的大小在编译时使用模板参数进行检查,因此不会超出范围


我确信有更奇特的方法来修改它。这是一个初步尝试。我认为你可以用类来弥补编译器的任何缺点。

一个不使用堆的解决方案是使用
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){};
};
#包括
常量boost::数组aa={{2,3};
甲级{
常量boost::数组b;
A():b(aa){};
};

通过acce模拟常量数组怎么样
#include <boost/array.hpp>

const boost::array<int, 2> aa={ { 2, 3} };

class A {
    const boost::array<int, 2> b;
    A():b(aa){};
};
class a {
    int privateB[2];
public:
    a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; }
    int b(const int idx) { return privateB[idx]; }
}
a aobj(2,3);    // initialize "constant array" b[]
n = aobj.b(1);  // read b[1] (write impossible from here)
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;
}