Intereting Posts
В C ++, когда я передаю значение в функцию, всегда ли он преобразуется в подходящий тип? Ошибка с оператором копирования / присваивания для classа, который имеет переменную std :: atomic member C ++ Microsoft: как связать uuid / guid с специализацией шаблона Карта памяти объекта classа C ++ Преобразование C ++ из строки в идентификатор объекта Ctor не допускается тип возврата найти элемент большинства элементов в массиве Быстрое ввод параметров командной строки для отладки Visual Studio? Сломанные библиотеки c ++ std на macOS High Sierra 10.13 Итераторы STL гарантируют действительность после изменения коллекции? SFINAE для функции члена classа (один компилирует другой) Проблема доступа членов classа C ++ с шаблонами Как преобразовать шестнадцатеричные числа в символ в c ++? Осуществляет неперное число (e) с функцией рекурсии Не удалось подключиться к общей библиотеке OpenCV (Linux)

Объявление массива внутри classа и установка его размера с помощью конструктора

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

Это код конструктора:

Tarray(int s): start_size(s){ } 

Это код, который устанавливает размер массива:

 const int start_size; T this_array[start_size]; 

Это весь файл:

 #ifndef TARRAY_H_ #define TARRAY_H_ template class Tarray { private: const int start_size; T this_array[start_size]; int array_size; public: Tarray(int s): start_size(s){ } ~Tarray(){ delete[] this_array; } T & operator[](int i){ return this_array[i]; } }; #endif /* TARRAY_H_ */ 

Это ошибки, которые я получаю:

 ..\/template_array/Tarray.h:16:24: error: 'Tarray::start_size' cannot appear in a constant-expression ..\/template_array/Tarray.h:16:34: error: 'new' cannot appear in a constant-expression ..\/template_array/Tarray.h:16:34: error: ISO C++ forbids initialization of member 'this_array' [-fpermissive] ..\/template_array/Tarray.h:16:34: error: making 'this_array' static [-fpermissive] ..\/template_array/Tarray.h: In instantiation of 'Tarray': ..\Human.cpp:17:24: instantiated from here ..\/template_array/Tarray.h:16:34: error: invalid in-class initialization of static data member of non-integral type 'Person*' Build error occurred, build is stopped Time consumed: 343 ms. 

Сообщения об ошибках меняются, когда я пытаюсь настроить код, но это ошибки из этой конкретной сборки.

Спасибо за любую помощь

Причина, по которой вы получаете compiler errors, – это строка:

 T this_array[start_size]; 

Эта строка заставит ваш Tarray самом деле содержать start_size экземпляры T Он не будет содержать указатель или ссылку на эти экземпляры – они будут частью того же блока памяти, который содержит другие переменные экземпляра Tarray. Это заставило бы размер classа зависеть от start_size, а start_size не известно во время компиляции. Размер любого classа C ++ должен быть известен во время компиляции, это невозможно.

Существует два способа решить эту проблему:

  1. Выделите массив экземпляров T в куче, используя массив new. Это то, что делает std::vector . Написание такого classа и его правильное поведение при копировании / перемещении / расширении / etc сложны и утомительны, поэтому я бы рекомендовал вместо этого использовать std::vector .
  2. Зафиксировать количество экземпляров T и передать его в качестве параметра шаблона

то есть:

 template class TArray { ... T this_array[N]; ... } 

Это то, что std :: array (только C ++ 11) и boost :: array do. Опять же, я бы рекомендовал использовать один из них вместо того, чтобы писать свои собственные. Если это не домашняя работа, конечно …

Наконец, стоит отметить, что это ошибка:

 ~Tarray(){ delete[] this_array; } 

this_array не был назначен new , поэтому его не следует delete . Если массив является частью classа, как он есть (вместо того, чтобы отдельно распределять кучу и принадлежать classу), он по умолчанию будет уничтожен вместе с остальной частью classа. Вызов delete не только лишний, это почти наверняка приведет к сбою.

std::vector – это именно инструмент для этой работы:

 template class Tarray { private: std::vector this_array; public: Tarray(int s): this_array(s){ } ~Tarray(){ } T & operator[](int i){ return this_array[i]; } }; 

Следующий код делает что-то подобное, но не использует конструктор:

 #ifndef TARRAY_H_ #define TARRAY_H_ template class Tarray { private: T this_array[SizeT]; public: Tarray() {} ~Tarray() {} T & operator[](int i){ return this_array[i]; } }; #endif /* TARRAY_H_ */ 

и вы можете использовать его следующим образом:

 TArray<10> myArray; 

Вы должны создать массив во время выполнения.

 template class Tarray { private: const int start_size; T* this_array; int array_size; Tarray( const Tarrat& inObj ); // no copy public: Tarray(int s): start_size(s), this_array( new T[s] ) { } ~Tarray(){ delete[] this_array; } T & operator[](int i){ return this_array[i]; } }; 

Обратите внимание: для этого T должен иметь конструктор по умолчанию (то есть конструктор, который не принимает аргументов).

Вместо этого используйте std :: vector и сделайте жизнь простой для себя. 🙂

(Если вам нужен массив фиксированного размера, тогда std :: array может быть возможно, я думаю, что это на C ++ 11, если нет, то у boost, вероятно, есть реализация).

Если вы настаиваете на том, что этот обычный синтаксис массива, хотя, как если бы вы использовали ye-olde C, вам нужно будет использовать параметр шаблона, так что ваш шаблонный class имеет два аргумента: один для «T», который уже имеет теперь и еще один для размера массива.

Вы делаете жизнь особенно сложной, управляя этим массивом самостоятельно – если вы чувствуете, что вам нужно определить деструктор, вы действительно должны определить конструктор копирования в дополнение к конструктору. (Это называется Правилом Большой тройки, если я правильно помню) вместо этого полагаться на RAII и избегать того, чтобы когда-либо явным образом вызывать оператор delete или delete [] самостоятельно.