Pergunta

Eu tenho a aula a seguir em C ++:

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

    // and here's the constructor
    a(void);
}

A questão é: como faço para inicializar B na lista de inicialização, já que não consigo inicializar dentro do corpo da função do construtor, porque B é const?

Isso não funciona:

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

Editar: o caso em questão é quando posso ter valores diferentes para b Para casos diferentes, mas os valores são conhecidos por serem constantes durante a vida útil da instância.

Foi útil?

Solução

Como os outros disseram, o ISO C ++ não suporta isso. Mas você pode alternar a solução. Basta usar o STD :: Vector.

int* a = new int[N];
// fill a

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};

Outras dicas

Com C ++ 11, a resposta a esta pergunta mudou agora 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() {
 a a;
}

Não é possível no padrão atual. Eu acredito que você poderá fazer isso em C ++ 0x usando listas de inicializador (veja Uma breve olhada em C ++ 0x, por Bjarne Stroustrup, para obter mais informações sobre listas de inicializadores e outros recursos nocivos de C ++ 0x).

std::vector usa a pilha. Nossa, que desperdício seria apenas por causa de um const Verifique em sanidade. O ponto de std::vector é um crescimento dinâmico em tempo de execução, e nenhuma verificação antiga de sintaxe que deve ser feita em tempo de compilação. Se você não vai crescer, crie uma classe para embrulhar uma matriz normal.

#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 e ConstFixedSizeArray são reutilizáveis.

O primeiro permite os limites de tempo de execução, a verificação ao inicializar a matriz (o mesmo que um vetor pode), que pode se tornar mais tarde const Após esta inicialização.

O segundo permite que a matriz seja alocada lado de dentro Outro objeto, que pode estar na pilha ou simplesmente a pilha, se é aí que o objeto está. Não há perda de tempo alocando a partir da pilha. Ele também executa o tempo de compilação, verificando const na matriz.

b_filler é uma pequena classe privada para fornecer os valores de inicialização. O tamanho da matriz é verificado em tempo de compilação 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 aulas.

O ISO Standard C ++ não permite que você faça isso. Se o fizesse, a sintaxe provavelmente seria:

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

Ou algo nesse sentido. Da sua pergunta, parece que o que você deseja é um membro constante da classe (também conhecido como estático) que é a matriz. C ++ permite que você faça isso. Igual a:

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

A::a => 0, 1

Agora, é claro, como este é um membro da classe estática, é o mesmo para cada instância da classe A. Se não é isso que você deseja, ou seja O erro de tentar fazer a matriz const. Você deveria estar apenas fazendo isso:

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

Onde tenho uma matriz constante, sempre foi feito como estática. Se você pode aceitar isso, esse código deve compilar e executar.

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

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

Veja isso:

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

:)

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

#include <boost/array.hpp>

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

class A {
    const boost::array<int, 2> b;
    A():b(aa){};
};

Que tal emular uma matriz const através de uma função de acessador? 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]; }
}

Porque um :: privateb é privado, é efetivamente constante fora de ::, e você pode acessá -lo 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 classes, também poderá proteger o PrivateB das funções de membros. Isso pode ser feito herdando um; Mas acho que prefiro John Harrison's Comp.lang.c ++ postagem usando uma classe const.

É interessante

readonly DateTime a = DateTime.Now;

Eu concordo, se você tiver uma matriz predefinida const, também poderá torná-la estática. Nesse ponto, você pode usar esta sintaxe 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 os '10' constantes. O motivo é claro, porém, ele precisa saber como executar o acesso à matriz. Uma alternativa possível é usar #define, mas não gosto desse método e eu #Undef no final do cabeçalho, com um comentário para editar lá no CPP também, caso se altere.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top