![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Возможно, данная тема уже пробегала на форуме. Однако, в поиске не нашел.
Итак, проблема следующая. Есть некий класс, у которого есть константное поле. Раз поле константное, то оно должно ициализироваться в конструкторе. Но мне нужно создать (динамически) массив элементов данного класса, причем каждому элементу нужно задать свои параметры конструктора. Какие есть варианты, кроме malloc + placement new (и связанных потом с этим извращений)? |
|||
|
||||
vinter |
|
|||
![]() Explorer ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2735 Регистрация: 1.4.2006 Где: Н.Новгород Репутация: 13 Всего: 56 |
остается еще явная инициализация, по другому вроде никак.
|
|||
|
||||
threef |
|
|||
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 375 Регистрация: 27.10.2005 Где: Запорожье Репутация: 9 Всего: 10 |
Синтаксически создать массив констант нельзя. Предлагались статические варианты или,ИМХО лучший - создать структуру, содержащую массив. Ее-то и можно проинициализировать в конструкторе.
|
|||
|
||||
Xenon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1529 Регистрация: 12.4.2006 Репутация: 11 Всего: 50 |
... Недопонял
![]() Это сообщение отредактировал(а) Xenon - 7.4.2007, 02:26 |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
threef, через список инициализаторов не пойдет. Мне нужен полноценный вызов конструктора с несколькими параметрами для каждого элемента....
|
|||
|
||||
Xenon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1529 Регистрация: 12.4.2006 Репутация: 11 Всего: 50 |
Может так?
Это сообщение отредактировал(а) Xenon - 7.4.2007, 12:45 |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Xenon, честно - не понял, что ты этим хотел сказать...
Мне при создании каждого элемента нужно ему в конструктор передать разные параметры... то есть мне надо сделать код, который будет работать как:
|
|||
|
||||
Daevaorn |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 2155 Регистрация: 29.11.2004 Где: Москва Репутация: 51 Всего: 70 |
||||
|
||||
Xenon |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1529 Регистрация: 12.4.2006 Репутация: 11 Всего: 50 |
JackYF, Я просто не очень понял что ты хотел. Исходя из заголовка я понял, что тебе нужен в классе константный динамический массив, который ты сможешь иницилизировать значениями, переданными в конструктор. Вот я тебе исходя из этих данных накидал пример.
Какая у тебя задача-то стоит? Зачем ЭТО? |
|||
|
||||
likehood |
|
|||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
JackYF, может это подойдет.
|
|||
|
||||
likehood |
|
|||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
можно еще вместо массива использовать вектор:
|
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
по-моему, тоже не пойдет. Вектор для присваивания будет использовать стандартную семантику присваивания, то есть operator=. Что в данное случае опять-таки недопустимо, присваивание константным элементам класса можно только в конструкторе. Вообще говоря, такая задача возникает уже второй раз... Зачем было первый, не помню. А вот вкратце кусок задачи - постараюсь объяснить... Есть класс. В котором содержится массив объектов. Массив public. Каждый объект содержит содержит несколько полей, из которых пользователь может все читать, но только часть писать. Те 2 поля, которые константные, инициализируются один раз при создании и больше не изменяются. Я подумал, что с точки зрения семантики лучше всего сделать было их константными, и тогда вопрос решался сам собой - данные инициализировались в надклассе массива, а потом можно было выдать пользователю данный массив. Пока писал, назрело, правда, еще одно решение... Сделать эти поля не константыми, а приватными у класса, фукнцию их чтения public, функцию их записи в приват и френдом надкласс. Да, это выход. Но это менее красиво... Да ну и вообще интересно с той точки зрения, что вообще с точки зрения программиста желания сделать массив с описанными мной свойствами возможно; и для компилятора, в общем-то, не проблема... Но вот не получается. |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Нет, не пойдет... опять все сводится к создание уже созданного массива значений и присваивания. Ни массива у меня нету и быть не может (а зачем мне тогда делать еще один? я лучше указатель создам), ни присваивания... (выше написал, почему). |
|||
|
||||
likehood |
|
||||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
Лучше покажу работающий код, а уж ты решай - пойдет он тебе или нет.
|
||||
|
|||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Срочно меняй свои представления о красоте! ![]() Один (уж не помню кто) из столпов программирования писал, что любую проблемму в программировании можно решить добавлением нужного числа прокладок в нужные места. Цитирую не дословно, но смысл тот. Вот и здесь то же самое, treef уже предлагал: дополнительная структура, содержащая твой массив. массив в структуре не константный, поэтому инициализируй его как хочешь. А саму структуру в объемлющем классе сделай константной. Точно, была уже такая тема, и там это предлагали, может даже я... Но лучше так не делай, а все спрячь подальше. Public-данные - это ЗЛО! -------------------- ... |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
likehood, мне надо будет отдавать пользователю ссылки на элементы массива. В данном случае тип элементов foo_local, о котором пользовает не знает и не узнает, так как он локальный.
Ну, не всегда. Особенно если они константные... чем? уже созданным внешне массивом? Как хочу? Дык вот я и хочу! Вызвать разные конструкторы для разных элементов массива. Но как? Проблема - инициализация массива! Ы, тоже не мой выход. Некоторые данные должны остаться public. Earnest, вариант threef'a не подходит. Он предлагает инициализировать надструктуру. Опять-таки - чем? У меня не POD-данные, чтобы их в инициализаторе прописывать между фигурными скобками... Задача - вызов конструкторов. И без локальных классов, мне потом надо будет эти ссылки на эти данные выводить наружу. Подводя по крайней мере промежуточный итог, резюмирую... не буду предоставлять public-const данные, сделаю через функции. Но вот абстрактный вопрос инициализации массива до сих пор не решен. Скорее всего, все-таки нельзя. А жалко. |
|||
|
||||
Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
Если массив не константный, то никто не мешает писать в конструкторе структуры:
a[0] = XXX; a[1] = YYY; и т.д. Нужно только позаботиться, чтобы элементы массива имели default-конструкторы. Что ты передашь в надструктуру для инициализации - твоя проблема, хоть из файла данные читай. Ты писал изначально о невозможности вызвать конструкторы для каждого элемента массива. Так вот, эта проблема решается в рамках описанного подхода. А как ты разом передашь для разных элементов инициализирующие данные - совсем другая проблема. -------------------- ... |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Operator= не подходит... Уже говорил же ж. Если делать константными данными. Решение с помощью закрытия данных и работы через функции принято. Вопрос, как вызвать конструкторы элементов массива. Без использования операторов=. Просто абстрагируясь от моей проблемы: как вызвать <u>конструкторы</u> элементов массива. Не присваивания потом или через внешние структуры. Сам факт. Нет - значит нет, дело же такое ![]() |
|||
|
||||
likehood |
|
|||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
Вообще-то, в моем примере тип массива Foo*, так что никаких проблем. Приведение к базовому классу еще никто не отменял. |
|||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Соглашусь. Но проблема прямого вызова конструкторов не решена. Мне надо это запихнуть в массив без operator=. Если выдавать элементы по одному, то такое не выйдет. |
|||
|
||||
SerpentVV |
|
||||||||||||||
Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 27.11.2006 Где: Астрахань Репутация: 1 Всего: 1 |
Поля-массивы в классе
До сих пор в качестве полей мы использовали только скалярные переменные. Но в С++ нет запрета объявлять в классе поле-массив. Естественно, размер класса с полем-массивом увеличивается на размер массива. Однако использование массива в классе имеет некоторые нюансы, связанные с инициализацией . Начнем разбираться с этим вопросом на самом простом примере (листинг 2.23), в котором объявляются и инициализируются несколько полей-массивов.
В классе Arrays объявлено три поля-массива: m0, m1 и m2. Как видим, задать количество элементов массива можно либо явной константой, либо константным выражением со статическими и/или нумерованными константами, причем константы должны быть определены раньше массива. Задавать количество элементов поля-массива обязательно. Конструктор без аргументов обнуляет массивы, выполняя цикл в теле. Такой способ инициализации поля-массива — в теле конструктора — является наиболее простым. Это позволяет присвоить элементам массива любые значения. Однако наиболее часто выполняется обнуление, поэтому для массивов разрешается применять инициализацию нулем. Тогда наш конструктор выглядит значительно проще:
Для массива объектов некоторого типа такая запись означает вызов конструктора по умолчанию (без аргументов), и не забудьте, что этот вызов выполняется для каждого элемента массива. К сожалению, применение списков инициализации для полей-массивов этим и ограничивается — в скобках нельзя ничего указывать. Явная инициализация не проходит даже для символьных массивов. Например, если мы объявим в классе Arrays символьный массив
и попытаемся в списке инициализации конструктора присвоить этому массиву символьную константу,
то в системе Visual C++.NET 2003 получим сообщение об ошибке: error C2536: 'Arrays::Arrays::s' : cannot specify explicit initializer for arrays нельзя определять явный инициализатор для массивов Однако мы можем прописать в классе поле-указатель на символ
и инициализировать его символьной константой в списке инициализации конструктора, как показано выше. Как это ни странно, но большие проблемы возникают при попытках объявить в классе константный массив встроенного типа! Как мы выяснили выше, константы не могут быть проинициализированы в теле конструктора и инициализируются только в списке инициализации конструктора. Однако для константного массива встроенного типа не работает даже инициализация нулем. ПРИМЕЧАНИЕ Этот вопрос практически не отражен в стандарте, поэтому компиляторы ведут себя по-разному. В системе Visual C++.NET 2003 выдается ошибка компиляции C2439, а Borland C++ Builder 6 выдает только предупреждение W8038 о том, что массив не инициализируется. Не проходит и отмена константности. Например, мы пропишем массив m0 как константный, а в теле конструктора пропишем инициализацию в цикле
И система Visual C++.NET 2003, и Borland C++ Builder 6 откажутся компилировать такой цикл. Удивительно, но для константного массива объектов не встроенного типа задавать инициализацию нулем разрешается. Для этого в классе должен быть определен конструктор без аргументов, который вызывается для инициализации каждого элемента константного поля-массива. Например, вполне можно инициализировать константный массив строк,
прописав в списке инициализации конструктора инициализацию «нулем» ss(). Как реально инициализируется такой массив, конечно, зависит от реализации конструктора по умолчанию. |
||||||||||||||
|
|||||||||||||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
SerpentVV, это все было к чему?
|
|||
|
||||
likehood |
|
|||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
||||
|
||||
JackYF |
|
|||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Задача - вызов конструкторов для каждого элемента массива. Список инициализации работает только для POD-типов, тем более значения, передаваемые в конструктор, мне не известны в начале программы. |
|||
|
||||
likehood |
|
|||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
Ну так в моем примере передаваемые значения и вычисляются во время работы программы. Кстати, почему это список инициализации работает только для POD-типов?
Добавлено через 2 минуты и 53 секунды Может мы говорим о разных вещах? ![]() Я говорю об этом посте. |
|||
|
||||
JackYF |
|
||||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Хм... приведи контрпример.
да... недосмотрел я тогда, видать. Возможно, это выход. Попробую применить. Спасибо. Ввиду этого дела... там где раньше в постах переборщил, извините... хорошо же меня понесло. |
||||
|
|||||
likehood |
|
|||
666 ![]() ![]() Профиль Группа: Участник Сообщений: 536 Регистрация: 21.12.2005 Репутация: 8 Всего: 24 |
Все же локальные классы - довольно экзотическая вещь. Пожалуй, лучшем вариантом будет предложенный Earnest. Видимо, я тебя неправильно понял. Ты, наверное, под списком инициализации имел ввиду пример threef'а, а я подумал о другом. В таком случае согласен насчет POD-типов. Разве ж это переборщил. Тут такие перлы иногда выдают... ![]() |
|||
|
||||
SerpentVV |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 27.11.2006 Где: Астрахань Репутация: 1 Всего: 1 |
Это к тому, что в списке инициализации вызывается конструктор по умолчанию - для неPOD-типов. Во-вторых, к тому, что о полях-константных массивах в стандарте нет практически ничего. В третьих, несколько противоречивая постановка: инициализировать константный массив значениями, которые не известны в начале работы программы... Тогда это - не константный массив, если значения констант неизвестны при компиляции... Если есть желание просто защитить от изменений - нет нужны объявлять массив константным... Можно решить этот вопрос на уровне прав доступа... |
|||
|
||||
JackYF |
|
||||
![]() полуавантюрист ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 5814 Регистрация: 28.8.2004 Где: страна тысячи озё р Репутация: 18 Всего: 162 |
Никаких противоречий...
Такой код тебя не смущает? А ведь значение явно не будет известно на этапе компиляции... Так и у меня. У меня некоторые поля класса константные... Которые, естественно, инициализируются в конструкторе. Не по-умолчанию... А в принципе, как минимум два пути решения вопроса уже озвучены. 1) с помощью прав доступа 2) с помощью локальных классов Всем спасибо, тему можно закрывать. |
||||
|
|||||
SerpentVV |
|
|||
Шустрый ![]() Профиль Группа: Участник Сообщений: 52 Регистрация: 27.11.2006 Где: Астрахань Репутация: 1 Всего: 1 |
Ага, понял... Логическая константность, естественно, не всегда равна физической...
![]() |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |