| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Общие вопросы > variadic parameters to base class constructor |
| Автор: InvalidProperty 29.1.2010, 17:05 | ||||||||||
| Передо мной возникла проблема, решение которой я считаю достойным публикации, дабы остальное сообщество могло бы найти решение поставленной проблемы по возможности быстрее, чем это удалось мне. Преамбула: Данный метод более всего подойдет для наследования классов исключений, базовый класс которых должен содержать строку описания исключения. Идея: Имеется базовый класс, конструктор которого принимает переменное число аргументов
Имеется дочерний класс. Его конструктор также должен принимать переменное число аргументов и создавать базовый класс. Постановка вопроса: Как передать переменное число аргументов из конструктора дочернего класса в конструктор базового? Размышления: Чтобы произвести создание базового класса из конструктора дочернего с указанием некоторых параметров для конструктора базового класса, нужно написать примерно следующее:
Но такая махинация для переменного числа параметров потерпит фиаско. Решение: В базовом классе создается статическая функция, которая будет отвечать за упаковку переменных параметров в строку:
и это будет работать!. Но! Как только мы попытаемся вызвать конструктор либо базового, либо дочернего класса, передавая строку, лежащую на стеке, или в статической памяти, приложение вылетит:
Для того, чтобы решить проблему, нужно создать некую структуру, которая будет содержать в себе строку, передаваемую конструкторам. Определение этой структуры ДОЛЖНО находиться в базовом классе, чтобы избежать создания такой структуры напрямую. Полный код решения:
Надеюсь, пояснений к коду не потребуется, но готов ответить на все вопросы |
| Автор: InvalidProperty 29.1.2010, 17:40 | ||
т.о. мы можем написать что-то вроде
и получим именно то, что хотим |
| Автор: zim22 29.1.2010, 17:54 | ||||
вот так
|
| Автор: InvalidProperty 29.1.2010, 17:56 |
| zim22, задача заключалась в передачи из конструктора дочернего класса именно тех же переменных параметров, что были переданы в него, а не просто каких-то Добавлено через 59 секунд mes, вторым постом я привел строку, которую можно использовать, применив данный метод Добавлено через 2 минуты и 11 секунд zim22, тем более, молодой человек, судя по коду, который Вы привели, Вы не прочитали пост вообще |
| Автор: zim22 29.1.2010, 18:08 | ||
я хоть свой возраст указал в инфо. насколько же вы молодой или старый - могу лишь догадываться. но в одном я уверен на 100% - есть более изящный метод решения вашей теоретической проблемы. *** и вообще, причём здесь возраст? "одни с годами умнеют - другие просто становятся старше." |
| Автор: InvalidProperty 29.1.2010, 18:10 | ||
так а я ведь всегда за здоровую критику. Давайте обсудим Ваш метод |
| Автор: zim22 29.1.2010, 18:27 |
| InvalidProperty, ок. напиши проблему, решение которой ты видишь только через использование ellipsis'a. я попробую решить её без них. |
| Автор: InvalidProperty 29.1.2010, 18:58 | ||
zim22, да что далеко ходить? Мне нужен класс исключений, который наследован от некоторого базового класса исключений. Нужно, чтобы и дочерний и базовый класс поддерживали конструкцию выбрасывания исключений с переменным числом параметров. Как Вы видите ее решение?
|
| Автор: zim22 29.1.2010, 19:02 | ||
это не проблема. это деталь реализации. *** примеры проблем: 1) есть картотека. для каждой из записей картотеки нужно применять разные алгоритмы анализа в зависимости от типа записи. 2) ... |
| Автор: InvalidProperty 29.1.2010, 19:12 |
| zim22, Вы к чему это сказали? Вы вообще топик этот прочитали или просто пустились в философию? Топик посвящен конкретной теме. Если есть иное решение, то покажите, и мы его обсудим, а иначе получается, что Вы просто льете воду. Зачем топик засорять? |
| Автор: Леопольд 29.1.2010, 19:32 |
| erased И вообще, элипсис это рудимент доставшийся от С... |
| Автор: NewDima 29.1.2010, 19:40 | ||
а я извращенец
|
| Автор: zim22 29.1.2010, 19:48 | ||
проведу аналогию. уж люблю я их
мораль сей басни такова: не нужно решать задачу неправильными методами. чтобы узнать какой метод правильный - нужно сначала понять саму задачу. |
| Автор: andrew_121 29.1.2010, 20:05 | ||||
философ епс ну расскажи что думаешь об этом. меня тоже такая задача посещает время от времени. |
| Автор: baldina 29.1.2010, 20:24 |
| InvalidProperty, при помощи синтаксиса С++ данную проблему изящно не решить. ковыряясь только в конструкторах это невозможно. Однако возник вопрос: что делает конструктор базового класса с переменным числом параметров, тип которых не проверяется в процессе компиляции? вероятно скармливает тому же vsnprintf. Тогда следующий вопрос - зачем классу исключений вообще этим заниматься? пусть конструирует строку тот, кто генерирует исключение, а класс исключения работает с постоянным числом параметров. Всё, проблемы нет. Обратите внимание: ваш pack() - совершенно инородный элемент в классе, класс нагружен не свойственным ему функционалом. Разделите функционал и проблема исчезнет. |
| Автор: zim22 29.1.2010, 20:26 | ||||
вот самый простой вариант. чем не устраивает?
|
| Автор: baldina 29.1.2010, 20:29 | ||
| в бусте кстати есть всякие форматтеры, которые позволяют конструировать на лету строки, имеющие сложный формат. это я к тому, что проблема форматирования строк не нова и давно решена, а класс исключения видимо будет ругаться в окошках. чем? правильно, строками. предваряя возможную дискуссию о разном числе неких разнотипных свойств, которые надо обрабатывать классу исключения, предложу в этом случае воспользоваться std::vector <boost::variant> или std::vector <boost::any>. Добавлено через 3 минуты и 7 секунд
|
| Автор: andrew_121 29.1.2010, 20:38 | ||||
это верно. но наверняка не только мне и InvalidProperty хотелось бы получить такую возможность. и желательно не только строковое сообщение. было бы супер! пример:
в примере я привел только передачу двух значений в конструктор, так как было бы не плохо чтоб остальные свойства заполнялись сами. типа макросами. или еще как-то. |
| Автор: baldina 29.1.2010, 20:41 | ||
andrew_121,
|
| Автор: andrew_121 29.1.2010, 20:45 |
| baldina, по моему раньше этого не было. во всяком случае я этого не заметил. еще думаю для этого подойдет boost.format |
| Автор: baldina 29.1.2010, 20:52 |
| andrew_121, кажется то, что выше, вы не читаете |
| Автор: andrew_121 29.1.2010, 21:21 |
этим - |
| Автор: Lazin 29.1.2010, 21:40 | ||||||
| как-же мы любим придумывать несуществующие проблемы и решать их я, в свою очередь, хочу предложить такой способ решения проблемы передачи переменного числа параметров в конструктор базового класса file: generate_ctor.ipp
other file:
тогда тебе как-то придется генерировать класс с переменным числом членов и недетерминированым набором методов |
| Автор: Lazin 29.1.2010, 21:58 | ||||||
я не вижу смысла в этом, класс исключения - Copy Constructable, поэтому можно писать так:
|
| Автор: mes 29.1.2010, 22:33 | ||||
тогда Вы неправильно поняли мое непонимание. Меня интересовала именно задача, а не неполучающийся способ ее реализовать. Ну вообщем тут уже много ответили, но еще раз проакцентирую внимание:
|
| Автор: InvalidProperty 30.1.2010, 16:58 | ||
меня навели на мысль еще одного варианта решения, который, как мне кажется, является более изящным, чем первый:
|
| Автор: Lazin 30.1.2010, 18:17 |
| этот вариант ни разу не изящный, обычный std::exception + boost.format - намного удобней, а главное обходятся без элипсиса |
| Автор: InvalidProperty 30.1.2010, 19:21 |
| Lazin, удобство понятие относительное и сугубо индивидуальное. Не нужно излишних холиваров. Я, к примеру, недолюбливаю сторонние библиотеки, а строка форматирования printf для меня выглядит привычнее и удобнее. |
| Автор: Lazin 30.1.2010, 20:00 | ||||||
я лично не понимаю, зачем все это, если можно просто отформатировать строку и передать ее в конструктор класса исключения, еще я не понимаю, почему не используется std::exception, а используется свой велосипед ну и на последок, если я захочу получить тот или иной параметр не в текстовом виде, что мне делать?
лично я бы не хотел работать в одной команде с вело-строителем любителем, потому-что вместо того, что-бы просто писать код, придется изучать аналоги уже хорошо известных вещей, вроде boost::format и std::exception вот к примеру вариант с boost::exception (не ручаюсь за правильность, пишу по памяти)
по крайней мере это будет понятно любому нормальному С++ программисту, а еще здесь можно получить любой из параметров или добавить туда новые параметры и заново бросить это исключение, можно передать его в другой поток |
| Автор: andrew_121 31.1.2010, 18:14 |
| мдя... http://evgeny-lazin.blogspot.com/2008/11/boostsystem.html |
| Автор: BEOWOLF 1.2.2010, 02:15 | ||||
А вообще подобного рода проблема решается другим, изящным способом - через использование объектов, содержащих свой конструктор/деструктор. То есть, вместо передачи const char* в качестве параметра, лучше передать const std::string&, в этом случае код всегда адекватно выполнится. Ну а если нужно передать форматированную строку, то пишите вот такую вот функцию:
Кроме того, незабываем использовать auto_ptr, если всё-таки есть работа с выделенными объектами и выброс исключений, а ещё лучше умные указатели |
| Автор: xvr 1.2.2010, 15:18 | ||
В таком случае я обычно делаю немного по другому:
|