inicializar uma matriz const em um inicializador de class em C ++

Eu tenho a seguinte class em C ++:

class a { const int b[2]; // other stuff follows // and here's the constructor a(void); } 

A questão é, como inicializo b na lista de boot, dado que não consigo inicializá-lo dentro do corpo da function do construtor, porque b é const ?

Isso não funciona:

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

Edit: O caso em questão é quando eu posso ter valores diferentes para b para instâncias diferentes, mas os valores são conhecidos como constantes durante a vida útil da instância.

Como os outros disseram, o ISO C ++ não suporta isso. Mas você pode contornar isso. Apenas use std :: vector.

 int* a = new int[N]; // fill a class C { const std::vector v; public: C():v(a, a+N) {} }; 

Com o C ++ 11, a resposta a esta pergunta agora mudou e você pode de fato fazer:

 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() { aa; } 

Não é possível no padrão atual. Eu acredito que você será capaz de fazer isso em C ++ 0x usando listas de boot (consulte Uma breve olhada em C ++ 0x , por Bjarne Stroustrup, para obter mais informações sobre listas de boot e outros resources C ++ 0x agradáveis).

std::vector usa o heap. Nossa, que desperdício seria apenas por causa de um teste de const . O ponto de std::vector é o crescimento dynamic em tempo de execução, não qualquer verificação de syntax antiga que deve ser feita em tempo de compilation. Se você não vai crescer, crie uma class para envolver uma matriz normal.

 #include  template  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() { ax; x.print_items(); return 0; } 

ConstFixedSizeArrayFiller e ConstFixedSizeArray são reutilizáveis.

O primeiro permite a verificação de limites de tempo de execução ao inicializar o array (o mesmo que um vetor pode), que posteriormente pode se tornar const após essa boot.

O segundo permite que o array seja alocado dentro de outro object, que poderia estar no heap ou simplesmente na pilha, se é onde está o object. Não há desperdício de tempo alocando do heap. Ele também executa verificação de const de tempo de compilation na matriz.

b_filler é uma pequena class privada para fornecer os valores de boot. O tamanho da matriz é verificado em tempo de compilation com os argumentos do modelo, portanto não há chance de sair dos limites.

Tenho certeza de que existem maneiras mais exóticas de modificar isso. Esta é uma facada inicial. Eu acho que você pode compensar qualquer falha do compilador com as classs.

O padrão ISO C ++ não permite que você faça isso. Se assim fosse, a syntax provavelmente seria:

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

Ou algo nesse sentido. De sua pergunta, realmente soa como o que você quer é um membro de class constante (aka estático) que é a matriz. C ++ deixa você fazer isso. Igual a:

 #include  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 saída sendo:

 A::a => 0, 1 

Agora, é claro, como esse é um membro de class estático, é o mesmo para todas as instâncias da class A. Se não é isso que você quer, ou seja, você quer que cada instância de A tenha valores de elementos diferentes na matriz. o erro de tentar fazer o array const para começar. Você deveria estar fazendo isso:

 #include  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 < < "va => " < < va[0] << ", " << va[1] << "\n"; return 0; } 

Onde eu tenho uma matriz constante, sempre foi feito como estático. Se você pode aceitar isso, esse código deve ser compilado e executado.

 #include  #include  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; } 

Você não pode fazer isso na lista de boot,

Veja isso:

http://www.cprogramming.com/tutorial/initialization-lists-c++.html

🙂

Uma solução sem usar o heap com std::vector é usar boost::array , embora você não possa inicializar os membros da matriz diretamente no construtor.

 #include  const boost::array aa={ { 2, 3} }; class A { const boost::array b; A():b(aa){}; }; 

Que tal emular um array const através de uma function acessadora? Não é estático (como você solicitou) e não requer stl ou qualquer outra biblioteca:

 class a { int privateB[2]; public: a(int b0,b1) { privateB[0]=b0; privateB[1]=b1; } int b(const int idx) { return privateB[idx]; } } 

Como a :: privateB é privada, ela é efetivamente constante fora de um ::, e você pode acessá-la de maneira semelhante a uma matriz, por exemplo

 a aobj(2,3); // initialize "constant array" b[] n = aobj.b(1); // read b[1] (write impossible from here) 

Se você estiver disposto a usar um par de classs, você poderá proteger adicionalmente o privateB das funções de membro. Isso pode ser feito herdando um; mas acho que prefiro o post comp.lang.c ++ de John Harrison usando uma class const.

Curiosamente, em C # você tem a palavra-chave const que traduz a constante estática de C ++, ao contrário de readonly, que pode ser definida apenas em construtores e inicializações, mesmo por não-constantes, ex:

 readonly DateTime a = DateTime.Now; 

Eu concordo, se você tem um array pré-definido const, pode torná-lo estático. Nesse ponto, você pode usar esta syntax interessante:

 //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", "!"}; 

no entanto, não encontrei uma maneira de contornar a constante ’10’. O motivo é claro, ele precisa saber como executar o access ao array. Uma alternativa possível é usar #define, mas eu não gosto desse método e eu #undef no final do header, com um comentário para editar lá no CPP, bem como no caso de uma mudança.