Как мне использовать функции-члены постоянных массивов в C ++?
Вопрос
Вот упрощенная версия того, что у меня есть (не работает):
прогр.ч:
...
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
const string c_astrExamples[] = {c_strExample1, c_strExample2};
...
prog.cpp:
...
int main()
{
int nLength = c_astrExamples.length();
for (int i = 0; i < nLength; i++)
cout << c_astrExamples[i] << "\n";
return 0;
}
...
Когда я пытаюсь выполнить сборку, я получаю следующую ошибку:ошибка C2228:слева от '.length' должен быть класс / структура / объединение
Ошибка возникает только тогда, когда я пытаюсь использовать функции-члены c_astrExamples.Если я заменю "c_astrExamples.length()" на число 2, все, похоже, будет работать правильно.
Я могу использовать функции-члены c_strExample1 и c_strExample2, поэтому я думаю, что поведение возникает из-за некоторой разницы между моим использованием строк и массивов строк.
Является ли моя инициализация в prog.h неправильной?Нужно ли мне что-то особенное в prog.cpp?
Решение
Массивы в C ++ не имеют функций-членов.Вы должны использовать коллекцию, подобную vector<string>
если вам нужен объект, или вычислите длину следующим образом:
int nLength = sizeof(c_astrExamples)/sizeof(c_astrExamples[0]);
Другие советы
Просто используй Вектор STL из строк вместо массива:
#include <string>
#include <vector>
using namespace std;
const string c_strExample1 = "ex1";
const string c_strExample2 = "ex2";
vector<string> c_astrExamples;
c_astrExamples.push_back(c_strExample1);
c_astrExamples.push_back(c_strExample2);
int main()
{
int nLength = c_astrExamples.size();
Массивы в C ++ унаследованы от C, который не был объектно-ориентированным.Таким образом, они не являются объектами и не имеют функций-членов.(В том, что они ведут себя как int
, float
и другие встроенные типы.) Из этой родословной вытекает больше проблем с array, таких как тот факт, что они легко (например, при передаче в функцию) распадаются на указатель на первый элемент без оставшейся информации о размере.
Обычный совет заключается в том, чтобы использовать std::vector
вместо этого, который представляет собой массив с динамически изменяемым размером.Однако, если вам размер массива известен во время компиляции и вам нужна константа, то тип массива boost'а (boost::array
, если ваш компилятор поддерживает стандартные расширения TR1 , также доступные как std::tr1::array
, стать std::array
в следующей версии стандарта C ++) - это то, что вы хотите.
Правка 1:
Безопасный способ получить длину массива в C ++ включает невероятную комбинацию шаблонов, указателей на функции и даже макроса, добавленного в смесь:
template <typename T, std::size_t N>
char (&array_size_helper(T (&)[N]))[N];
#define ARRAY_SIZE(Array_) (sizeof( array_size_helper(Array_) ))
Если вы (как и я) считаете это забавным, посмотрите на boost::array
.
Правка 2:
Как сказал дрибеас в комментарии, если вам не нужна константа времени компиляции, это
template <typename T, std::size_t N>
inline std::size_t array_size(T(&)[N])
{return N;}
этого достаточно (и гораздо легче читать и понимать).
c_astrExamples - это массив, в нем нет метода "length()".
В C ++ массивы не являются объектами и не имеют к ним никаких методов.Если вам нужно получить длину массива, вы могли бы использовать следующий макрос
#define COUNTOF( array ) ( sizeof( array )/sizeof( array[0] ) )
int nLength = COUNTOF(c_astrExamples);
Кроме того, остерегайтесь инициализации в заголовочном файле.Вы рискуете оскорбить компоновщика.
Тебе следовало бы:
прогр.ч:
extern const string c_strExample1;
extern const string c_strExample2;
extern const string c_astrExamples[];