инициализируйте массив константы в инициализаторе класса в C++

Я думаю, что важно подчеркнуть, что в Java нет такой вещи, как «Инициализация двойного браслеза». Веб-сайт Oracle не имеет этого термина. В этом примере используются две функции: анонимный класс и блок инициализатора. Похоже, что старый блок инициализатора был забыт разработчиками и вызвал некоторую путаницу в этой теме. Цитирование из Oracle docs :

Блоки инициализатора для переменных экземпляра выглядят так же, как и статические блоки инициализатора, но без статического ключевого слова:

{
    // whatever code is needed for initialization goes here
}

73
задан Lightness Races with Monica 7 April 2013 в 12:20
поделиться

8 ответов

Как другие сказал, C++ ISO не поддерживает это. Но Вы можете обходное решение это. Просто используйте станд.:: вектор вместо этого.

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

class C {
  const std::vector<int> v;
public:
  C():v(a, a+N) {}
};
32
ответ дан Weipeng L 24 November 2019 в 12:15
поделиться

Это не возможно в текущем стандарте. Я полагаю, что Вы будете в состоянии сделать это в C++ 0x использование списков инициализатора (см. Беглый взгляд А в C++ 0x , Bjarne Stroustrup, для получения дополнительной информации о списках инициализатора и другом хорошем C++ 0x функции).

25
ответ дан Luc Touraille 24 November 2019 в 12:15
поделиться

C++ стандарта ISO не позволяет Вам сделать это. Если бы это сделало, синтаксис, вероятно, был бы:

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. Если это не то, что Вы хотите, т.е. Вы хотите, чтобы каждый экземпляр имел различные значения элемента в массиве тогда, Вы делаете ошибку попытки сделать константу массива для начала. Необходимо просто делать это:

#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;
}
9
ответ дан orj 24 November 2019 в 12:15
поделиться

Где у меня есть постоянный массив, он всегда делался как статичный. Если можно признать, что, этот код должен скомпилировать и работать.

#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;
}
4
ответ дан Daniel Bungert 24 November 2019 в 12:15
поделиться

Вы не можете сделать, это из списка инициализации,

Взглянуло на это:

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

:)

4
ответ дан Nathan Fellman 24 November 2019 в 12:15
поделиться

интересно, что в C # у вас есть ключевое слово const, которое переводится в статическую константу C ++, в отличие от 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, но мне этот метод не нравится, и я ставлю #undef в конце заголовка с комментарием для редактирования там же на CPP в случае изменения.

2
ответ дан 24 November 2019 в 12:15
поделиться

std :: vector использует кучу. Боже, какая трата была бы только ради 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 после этой инициализации.

Второй позволяет разместить массив внутри другого объекта, который может находиться в куче или просто в стеке, если объект находится там. Нет необходимости тратить время на выделение из кучи. Он также выполняет проверку константы во время компиляции для массива.

b_filler - крошечный частный класс для предоставления значений инициализации. Размер массива проверяется во время компиляции с помощью аргументов шаблона, поэтому нет никаких шансов выйти за пределы.

Я уверен, что есть более экзотические способы изменить это. Это первый удар. Я думаю, что вы можете в значительной степени восполнить любой недостаток компилятора с помощью классов.

12
ответ дан 24 November 2019 в 12:15
поделиться

Решение без использования кучи с 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){};
};
3
ответ дан 24 November 2019 в 12:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: