LINUX.ORG.RU

[C++] Константные массивы - члены классов

 


0

0

Здравстуй, многоуважаемый all

С некоторых пор меня заинтересовала проблема - как сделать в классе переменную - константый массив определенного типа и размера, содержимое которого берется из агрумента конструктора?

В голову пришло примерно следующее решение:

template <typename T>
class const_array
{
public:
	const_array( const T* arr, int size )
		: m_data(0), m_size(size)
	{
		m_data = new T[m_size];
		for( int i = 0; i < m_size; i++ )
			m_data[i] = arr[i];
	}
	~const_array()
	{
		delete []m_data;
	}

	const T& operator[] (int pos) const
	{
		if( pos < 0 )
			pos = 0;
		if( pos >= m_size )
			pos = m_size - 1;
		return m_data[ pos ];
	}

	int size() const { return m_size; }

protected:
	T* m_data;
	const int m_size;
};


class demo
{
public:
	demo( const int* matrix, int size ) : m_ca(matrix, size) {}
protected:
	const_array<int> m_ca;
};

Т.е. делается спецкласс, реализующий свойства константного массива, который можно инициализировать прямо в списке инициализации.

И работает! Но существуют ли какие нибудь другие способы сотворить подобное, или так и придется через шаблоны?

Жду больших дискуссий :)


>С некоторых пор меня заинтересовала проблема - как сделать в классе переменную - константый массив определенного типа и размера, содержимое которого берется из агрумента конструктора?

2 my mind никак - const-поля надо инициализировать в списке инициализации, а массив в списке инициализации проиинициализировать нельзя. Наверно, прокатит std::vector который можно инициализировать двумя указателями - на начало и на конец Си - массива.

Absurd ★★★
()

> Жду больших дискуссий :)

C-плюшники в своем репертуаре -- сделать из мухи слона.

dilmah ★★★★★
()

#include <vector>

class demo
{
public:
   demo( const int* matrix, int size ) : m_ca(&matrix[0], &matrix[size]) {}
protected:
   const std::vector <int> m_ca;
};

Reset ★★★★★
()
Ответ на: комментарий от dilmah

А что ты предлагаешь делать, если нужна такая фишка

anonymous
()

Балин! Почему в C++ все настолько дубово? В Java final поля класса разрешено инициализировать в конструкторе. Что в принципе вполне логично.

Ian ★★
()
Ответ на: комментарий от Ian

>В Java final поля класса разрешено инициализировать в конструкторе.

Чтобы в С++ вернуть клиенту срез объекта "только для чтения" надо просто поставить квалификатор const. В Яве придется извращаться со всякими UnmodifiableList, и ито проверка будет в рантайме. Так что const в C++ проработан лучше - даже мне приходится это признать, что непросто, учитывая мое отношение к С++ как к чернобыльской катастрофе в софт-индустрии.

Absurd ★★★
()
Ответ на: комментарий от Ian

Не понял юмора. Ты хочешь, чтобы при выполнении конструктора члены класса ещё не были бы сконструированы? Нафига ж оно надо?

devinull ★★
()
Ответ на: комментарий от Absurd

> const в C++ проработан лучше - даже мне приходится это признать, что непросто, учитывая мое отношение к С++

Спорное суждение. const в С++ поверхностный и не распространяется на содержимое полей-указателей. Как следствие, нет логической const-антности, но правда есть некая концепция. По мне так лучше бы не вводили такой полу-фабрикат. Как говорится, ни два, ни полтора.

Кстати, ты прочитал мой пост о ключевом слове export в одной из прошлых тем в ответ на твое сообщение? Там было про шаблоны.

dave ★★★★★
()
Ответ на: комментарий от dave

>const в С++ поверхностный и не распространяется на содержимое полей-указателей.

И не должен. Есть константный указатель, а есть указатель на константу. Всё правильно.

devinull ★★
()
Ответ на: комментарий от dave

Во-первых как уже сказали в C++ два вида const'а. Во-вторых C++ низкоуровневый язык, а всякие там const/private/public и т.д. т.п. это всего лишь защита от дурака, которая легко обходится и смысла на неё 100% полагаться нет.

Reset ★★★★★
()

class demo {
 private:

  int* init_data(const int* matrix, int size) {
   int* result = new int[size];
   for (int i = 0; i < size; ++i)
    result[i] = matrix[i];
   return result;
  };

 public:
  const int* data;

  demo(const int* matrix, int size): data(init_data(matrix, size));
  ~demo() { delete[] data; };
}; 


А при желании и прокачанных скиллах иногда можно использовать
бустовскую лямбду :]

Jini ★★
()
Ответ на: комментарий от dave

>Кстати, ты прочитал мой пост о ключевом слове export в одной из прошлых тем в ответ на твое сообщение? Там было про шаблоны.

Неа - кинь ссылку плиз.

Absurd ★★★
()
Ответ на: комментарий от devinull

Да хочу. Потому что это разумно.

Не static поля должны быть проинициализированы во время создания объекта, то есть в конструкторе. final поля принадлежат объекту класса, а не классу, как static поля. Так почему для них нужно вводить дополнительные правила, отличные от инициализации "обычных" полей?

Возникает только одна проблема. Если ты решил воспользоваться этим final полем в конструкторе до его инициализации. Ну так это проблема решается на уровне компилятора. В Java он скажет, что variable might not be initialized.

Ian ★★
()
Ответ на: комментарий от Absurd

Тут я с тобой не могу не согласиться, но соглашаюсь с большой натяжкой. Вещи типа UnmodifiableList вполне соответствуют стилю программирования на Java. Тут стоит вопрос о любви/лютой_ненависти к Java так таковой.

К тому же эти UnmodifiableList очень легко реализуются. Но да, если их много - это немного дольше.

Ian ★★
()
Ответ на: комментарий от Reset

>#include <vector>

Действительно, можно и вектором обойтись)) Что-то я забыл что его можно инициализировать двумя итераторами

mint
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.