Название: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 05, 2011, 06:35 В С# у меня с этим проблем не было, т.к. делал все через интерфейсы и у них была возможность сделать проверку перед преобразованием в производный. Точнее я делал преобразование базового типа в интерфейс, а уже потом интерфейсом проверял, могу ли я преобразовать. А также я мог с помощью такой проверки сделать разветвление для преобразования в тот тип, который содержит базовый. Например в Qt я могу использовать QVariant и у него canConvert<NNumeric> (например для проверки на тип NNumeric).
Т.е. NDataTypes является базовым по отношению к производным NNumeric, NString, NLogical. Код: void NEngine::Writeln(qint32 ID) В условии с ID, dt передаются указатели, т.е. NDataTypes*. У меня вопрос такой, что нужно написать вместо variant.canConvert<NNumeric>() для проверки на тип, чтобы в случае истины выполнить преобразование в NNumeric и выполнить дальнейшие действия? Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 05, 2011, 10:11 Советую срочно почитать литературу по с++. Вижу непонимание базовых классов и принципов наследования.
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: _govorilka от Март 05, 2011, 10:38 Посмотрите исходник, как там реализована функция FwMLNode::cast<>(). Возможно, это вам поможет:
http://code.google.com/p/fireworks/source/browse/src/fwcore/fwml.h (http://code.google.com/p/fireworks/source/browse/src/fwcore/fwml.h) Хотя Бьярн Страустрап, наверное поможет больше ;)... Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 05, 2011, 11:39 Код: if (variant.canConvert<NNumeric>()) { В условии с ID, dt передаются указатели, т.е. NDataTypes*. У меня вопрос такой, что нужно написать вместо variant.canConvert<NNumeric>() для проверки на тип, чтобы в случае истины выполнить преобразование в NNumeric и выполнить дальнейшие действия? Код Заметим что возвращаемый указатель numeric может быть и не равен dt, более того, тип указателя dt может и не наследовать NNumeric Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 05, 2011, 11:53 Цитировать Чрезмерное применение понижающего приведения может служить признаком слишком бедного интерфейса базового класса (А. Александреску, Г.Саттер)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 05, 2011, 12:09 Цитировать Чрезмерное применение понижающего приведения может служить признаком слишком бедного интерфейса базового класса (А. Александреску, Г.Саттер)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 05, 2011, 12:13 Советую срочно почитать литературу по с++. Вижу непонимание базовых классов и принципов наследования. В том то вся и проблема, что я еще вчера это сделал. Но вот про dynamic_cast ничего не нашел путного, тем более у Бьерна, что очень странно. Но видать не до конца разобрал или что-то упустил из внимания. ;)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 05, 2011, 12:19 Igors, хватит спорить только ради того, чтобы спорить. Я просто процитировал двух человек, которые в с++ разбираются намного лучше нас с тобой вместе взятых. Если с чем-то не согласен, обращайся к ним.
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 05, 2011, 12:43 Так, к слову:
Возможности RTTI на dynamic_cast не заканчиваются) Есть ещё такая штука, как typeid Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Авварон от Март 05, 2011, 12:46 двух человек, которые в с++ разбираются намного лучше нас с тобой вместе взятых. Блин, сколько раз тебе говорил - не верь слепо прочитаному. Половина их мыслей неверна (причем незвисимо от того как они шарят - человеку просто надо было написать еще 1 предложение, вот он а бацнул что в голову пришло)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 05, 2011, 13:04 Ну вот еще один спорщик. :) Я не слепо верю, а обдумываю и соглашаюсь или не соглашаюсь.
Закончим офтоп в этой ветке. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: pastor от Март 05, 2011, 13:36 А о чем вы спорите: о термине "понижающее приведение" или о самой сути высказывания? :)
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 05, 2011, 13:40 pastor, о сути, как я понял.
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 05, 2011, 13:42 Моментик... Я за пивом сбегаю))
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 05, 2011, 13:44 Попкорн не забудь.
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 09:06 Спасибо за ссылки, на выходных разобрался с этим вопросом и все у меня работает, но осталось два вопроса. Сначала, опишу, что я сделал, а уж потом и вопросы задам. :)
Итак, в класс NNumeric, который ориентирован в операциях над его значениями работать как стековая переменная, добавил следующие строки кода: Код: //две строки ниже позволяют передать стековой переменной значения из указательной Т.о. NNumeric выполнять все, что и раньше, как стековая переменная, но теперь еще и сохраняется в базовом класса, как указатель (NNumeric*) и спокойно передается стековой переменной. Т.е. хранится он в виде указателя, а работа с ним ведется через стековую переменную. Вот здесь первый вопрос. У меня хоть и не содержится внутри класса своих указательных переменных и деструктор собирается транслятором (проше говоря он не прописан), а также в виде указателей он хранится в QList<NDataTypes*> Variables; и QStack<NDataTypes*> StackValue;, то не возникнет ли у меня утечки памяти? Теперь, то как у меня реализована та функция, о которой я в первом указывал: Код: void NeorgekEngine::NEngine::Writeln(qint32 ID) Вот здесь второй вопрос. Есть момент, когда dt имеет указатель не инициализированный класс. Т.е. был объявлен указатель, но без вызова конструктора, потом его присвоили dt. Но, в таком случае, при проверке dynamic_cast вылетает системная ошибка (точнее сигнал от системы). Через особые ситуации я его отловить не смог (даже, через catch(...) ). Вот мне интересно, есть ли способ от него защититься или все же следить за тем, чтобы у указательных объектов перед из передачей указателю базового класса, использовались конструкторы? Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 09:09 Полагаю стоит дать код, еще базовых классов и самого NNumeric.
Базовые классы: Код: #ifndef DATATYPES_H NNumeric: Код: include <cmath> Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: blood_shadow от Март 07, 2011, 11:25 У меня вопрос такой, что нужно написать вместо variant.canConvert<NNumeric>() для проверки на тип, чтобы в случае истины выполнить преобразование в NNumeric и выполнить дальнейшие действия? есть такая штука с стандартного С++ typeid() , которая проверяет к какому классу принадлежит объект или указатель в данный момент времениНазвание: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 07, 2011, 12:00 Цитировать Вот здесь второй вопрос. Есть момент, когда dt имеет указатель не инициализированный класс. Т.е. был объявлен указатель, но без вызова конструктора, потом его присвоили dt. Но, в таком случае, при проверке dynamic_cast вылетает системная ошибка (точнее сигнал от системы). Через особые ситуации я его отловить не смог (даже, через catch(...) ). Вот мне интересно, есть ли способ от него защититься или все же следить за тем, чтобы у указательных объектов перед из передачей указателю базового класса, использовались конструкторы? Вот, вот, вместо того, чтобы сесть, тчательно подумать над архитектурой, проникнуться теорией, а уже потом имея фундамент, что то ваять, лучше тратить время на то, чтобы учится создавать костыли и костыли для костылей и т.д.Герой на героине, Героине на героине.. ;D Цитировать не возникнет ли у меня утечки памяти? Возникнет, обязательно)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: blood_shadow от Март 07, 2011, 12:15 Вот здесь второй вопрос. Есть момент, когда dt имеет указатель не инициализированный класс. Т.е. был объявлен указатель, но без вызова конструктора, потом его присвоили dt. Но, в таком случае, при проверке dynamic_cast вылетает системная ошибка (точнее сигнал от системы). Через особые ситуации я его отловить не смог (даже, через catch(...) ). Вот мне интересно, есть ли способ от него защититься или все же следить за тем, чтобы у указательных объектов перед из передачей указателю базового класса, использовались конструкторы? чувак читай книжки, Код: NDataTypes* dt; создаются такие объекты через оператор new: Код: NDataTypes* dt = new NDataTypes(//то что в конструкторе) ссылается указатель, на объект а не класс(!!!), а так как ты еще не создал объект то это и вызывает падение этого оператора, класс - это описание(тип), объект- это физическая сущность(переменная) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 12:28 Вот здесь второй вопрос. Есть момент, когда dt имеет указатель не инициализированный класс. Т.е. был объявлен указатель, но без вызова конструктора, потом его присвоили dt. Но, в таком случае, при проверке dynamic_cast вылетает системная ошибка (точнее сигнал от системы). Через особые ситуации я его отловить не смог (даже, через catch(...) ). Вот мне интересно, есть ли способ от него защититься или все же следить за тем, чтобы у указательных объектов перед из передачей указателю базового класса, использовались конструкторы? Не видно как Вы объявились без конструктора, но если так то конечно никакие dynamic_cast и typeid работать не будут, т.к. именно код конструктора прописывает/заполняет RTTI (поэтому он и конструктор а не обычная ф-ция)Др. замечания if (dynamic_cast<NNumeric*>(dt) != NULL) { "Не ленивый" программист пишет одну строку дважды :)NNumeric numeric = dynamic_cast<NNumeric*>(dt); Код: //две строки ниже позволяют передать стековой переменной значения из указательной а) "this->" - так пишут на жабе, а здесь - ну можно, но если Вы хотите что-то подчеркнуть, а не просто так б) не стоит делать описание класса таким неопрятным, если считаете что нужен inline, а тело ф-ции не маленькое, то лучше так (в хедере но за рамками класса) Код Также в С/C++ принято имена переменных начинать с маленькой буквы в) Трудно понять что Вы хотите сделать. Зачем нужен конструктор принимающий указатель? Гораздо естественнее перекрыть конструктор копирования. Зачем перекрывать оператор "*" в поисках (ненужных) приключений? //если идентификатор равен -1, значит это либо временная переменная, либо константное значение Смысл (примерно) понятен, но тогда может сделать базовый класс (без ID) а затем унаследоваться, добавив ID и имя. А так разбираться каждый раз выяснять кто там локальный/глобальный - утомительноqint32 _id; Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 12:45 Вот, вот, вместо того, чтобы сесть, тчательно подумать над архитектурой, проникнуться теорией, а уже потом имея фундамент, что то ваять, лучше тратить время на то, чтобы учится создавать костыли и костыли для костылей и т.д. :) Ну я лично использую тот же метод что и Eten (ваять а там разберемся) и не считаю что это хуже. Просто надо более крытычно относиться к написанному и не бояться переделок. А "заложить фундамент" не всегда возможно, никогда не предусмотреть всего заранее.Герой на героине, Героине на героине.. ;D Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 07, 2011, 13:38 Но, в таком случае, при проверке dynamic_cast вылетает системная ошибка (точнее сигнал от системы). Через особые ситуации я его отловить не смог (даже, через catch(...) ). В принципе можно отловить на некоторых платформах, но вреда будет намного больше, чем пользы. Нельзя ли привести примеры типичного использования NNumeric? Просто непонятно, какую задачу решает определение операторов для указателя, почему нельзя так: NNumeric a, b, c; a = 12; b = .7; c = a + b; зачем тут NNumeric*? Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 13:43 Пардон за описание про указатель и объекты, увы не всегда точен в словах. Но на деле, для меня нет особой разницы, если код написан правильно, исполняет то машина, а не человек. Вот и забываю иногда про то, что пишу людям, а не компу. ::)
Спрашивал насчет утечек, т.к. раньше мне не доводилось использовать класс, который NNumeric* использует для хранения, а NNumeric для всего остального. Был бы у меня внутри указатель на что-то, которым я оперировал (как например в строках), тогда дело ясное. Без указателей, как у меня в NNumeric, также ясно. А когда храню в виде указателей и оперирую с объектом ввиде NNumeric, вот здесь озадачило. Просто я не понял, в каком месте у меня возникнет утечка. В самом NNumeric или в тех местах, где я храню. Сделать преобразование в NNumeric*, создать конструктор копирования для NNumeric* и оператор присвоения NNumeric*, пришлось сделать из-за той же логики, что и с ссылкой на объект. И как показала практика, я не могу типу NNumeric* присвоить указатель на тип NNumeric и в дальнейшем его использовать, как указатель. Поэтому в преобразовании NNumeric к NNumeric* создается объект типа NNumeric*, ему передаются все значения, потом его же и выдаю. Т.о. значения объекта созданного в стеке передаются объекту, созданному в куче, и последний возвращается в том типе, который нужен. А оператор присвоения и конструктор NNumeric* созданы по тем же причинам, что создают с параметром NNumeric&. Тем более, что у меня операции над объектом происходят, не как с NNumeric*, а как с NNumeric. Отсюда и такой код, т.е. использовать NNumeric для действий над ним практичнее так, а хранить в отдельном месте в виде указателя NNumeric*, через указатель на базовый класс. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 14:11 Но, в таком случае, при проверке dynamic_cast вылетает системная ошибка (точнее сигнал от системы). Через особые ситуации я его отловить не смог (даже, через catch(...) ). В принципе можно отловить на некоторых платформах, но вреда будет намного больше, чем пользы. Нельзя ли привести примеры типичного использования NNumeric? Просто непонятно, какую задачу решает определение операторов для указателя, почему нельзя так: NNumeric a, b, c; a = 12; b = .7; c = a + b; зачем тут NNumeric*? Класс NNumeric используется для хранения числа, операции проводятся уже в Си++ типах данных. Базовые классы у меня используются, как раз для хранения и иерархичности классов данных. Все операции NNumeric проводит так: Код: NNumeric a, b, c; Т.е. я преобразую NNumeric, для выполнения операций над его значением, в double, а потом использую автоматический конструктор с double, чтобы присвоить результат в "c", со всеми сопутствующими данными, которые использует сам движок. Преобразование в qint32 и float я использую для вывода значения, а также qint32 используется в тех операциях, где требуется работа только с целочисленными (например целочисленное деление). В классе нет перегруженных операторов арифметических операций, т.к. мне требуется удобная форма записи при обращению с памятью (получение из памяти и сохранение в память). Под памятью подразумевается место, где хранится экземпляр NNumeric. А т.к. у меня производится все именно, т.к. показано выше в коде и работа с базовыми классами и производными от них производится, через указатель (иначе я не встречал ни разу, у Страустрапа уж точно), то мне потребовалось сделать перегруженные операторы для указателей, чтобы сохранить работу класса как в коде выше. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 07, 2011, 14:17 А когда храню в виде указателей и оперирую с объектом ввиде NNumeric, вот здесь озадачило. Просто я не понял, в каком месте у меня возникнет утечка. В самом NNumeric или в тех местах, где я храню. Код
указатель на NNumeric удалён из стека, но нигде нет вызова delete dt, это утечка. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 14:19 в) Трудно понять что Вы хотите сделать. Зачем нужен конструктор принимающий указатель? Гораздо естественнее перекрыть конструктор копирования. Зачем перекрывать оператор "*" в поисках (ненужных) приключений? А на что можно напороться?! :-\ У меня все работает без "приключений", но вот без переопределения работы с "*" в определенных ситуациях, код излишне увеличится. Так оказалось удобнее и компактней. ;)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 14:54 Но на деле, для меня нет особой разницы, если код написан правильно, исполняет то машина, а не человек. Здесь позвольте с Вами не согласиться. Как человек пишет - так и думает. Сделать преобразование в NNumeric*, создать конструктор копирования для NNumeric* и оператор присвоения NNumeric*, пришлось сделать из-за той же логики, что и с ссылкой на объект. И как показала практика, я не могу типу NNumeric* присвоить указатель на тип NNumeric и в дальнейшем его использовать, как указатель. Поэтому в преобразовании NNumeric к NNumeric* создается объект типа NNumeric*, ему передаются все значения, потом его же и выдаю. Т.о. значения объекта созданного в стеке передаются объекту, созданному в куче, и последний возвращается в том типе, который нужен. А оператор присвоения и конструктор NNumeric* созданы по тем же причинам, что создают с параметром NNumeric&. Тем более, что у меня операции над объектом происходят, не как с NNumeric*, а как с NNumeric. Отсюда и такой код, т.е. использовать NNumeric для действий над ним практичнее так, а хранить в отдельном месте в виде указателя NNumeric*, через указатель на базовый класс. Если объект имеет ID, то полагается что оно уникально и двух объектов с одним ID быть не должно. Обычно указатели на такие объекты хранятся в какой-то таблице. Ну и перекрывайте конструктор копирования, оператор присваивания и деструктор чтобы обеспечить уникальность этого ID. Другой путь - для локальных объектов использовать упрощенный класс который не имеет никакого ID и имени. А у Вас мутность великая, понять мудрено :) Приведите максимально упрощенный пример где возникает проблема, никак не верится что нужны такие противоестественные хуки что Вы применяете.Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 07, 2011, 15:03 Класс NNumeric используется для хранения числа, операции проводятся уже в Си++ типах данных. Базовые классы у меня используются, как раз для хранения и иерархичности классов данных. Все операции NNumeric проводит так: Код
то же самое можно переписать без операторов от NNumeric*: Код
такой код и читать легче, потому что не задумываешься над вопросами типа "зачем и как тут объекту присваивается указатель?". Не нужно вообще использовать new там, где это не нужно. И совсем смущает последний кусок: Код , так значение dt просто потеряется, лик. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 07, 2011, 15:25 Вот, вот, вместо того, чтобы сесть, тчательно подумать над архитектурой, проникнуться теорией, а уже потом имея фундамент, что то ваять, лучше тратить время на то, чтобы учится создавать костыли и костыли для костылей и т.д. :) Ну я лично использую тот же метод что и Eten (ваять а там разберемся) и не считаю что это хуже. Просто надо более крытычно относиться к написанному и не бояться переделок. А "заложить фундамент" не всегда возможно, никогда не предусмотреть всего заранее.Герой на героине, Героине на героине.. ;D Не спорю, что всего заранее не предусмотреть. Но, "заложить фундамент" я понимаю как некий основной теор. минимум: как вообще другие с подобными проблемами справлялись, есть ли отточенные решения для этой ситуации, какие инструменты ит.д. И под архитектурой я вовсе не имею ввиду окончательный вариант, но некий интерплей между объектами, их обязанности, иерархия, какие то свойства основные.. Короче, хотел выразить мысль, что картина вырисовывается не из-за понятий, а из взаимоотношений между ними.. Как то так)) К тому же, хуже от того, чтобы вначале подумать, взять листочек с ручкой, почеркать, походить, покурить точно не будет) (разве что от покурить))) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 15:41 brankovic, спасибо, но я уже это понял, когда вы намекнули про утечку (этот момент я тоже исправил), поэтому там, где у себя лишним поставил деструктор для dt, его же и убрал. Работу с указателями привел потому, что вы спрашивали. А работа с указателем, которая была в них приведена, используется для получения NNumeric из тех мест, где он хранится в виде указателя на базовый класс. Если кто-то знает, как можно работать с производными и базовыми классами без указателей вообще, мне очень интересно посмотреть и узнать как это делается, т.к. Страустрап в своей книге все делал с помощью указателей. ;)
Цитата: Igors Здесь позвольте с Вами не согласиться. Как человек пишет - так и думает. Я с вами полностью согласен, но по своему опыту знаю, что отношусь к тем людям, у которых понимание опережает формулирование мыслей. Из-за этого иногда возникают не состыковки. Т.е. я все могу понять, но не всегда в силах выразить это правильно на словах. ::)Цитата: Igors Если объект имеет ID, то полагается что оно уникально и двух объектов с одним ID быть не должно. Обычно указатели на такие объекты хранятся в какой-то таблице. Ну и перекрывайте конструктор копирования, оператор присваивания и деструктор чтобы обеспечить уникальность этого ID. Другой путь - для локальных объектов использовать упрощенный класс который не имеет никакого ID и имени. А у Вас мутность великая, понять мудрено :) Приведите максимально упрощенный пример где возникает проблема, никак не верится что нужны такие противоестественные хуки что Вы применяете. ID тут не причем, он и имя используется в других целях. Ясное дело, что ID у меня будут уникальными, но следить за этим я предпочел другим объектом, который его хранит. А вот насчет разделения на локи и глобалы я не совсем уверен, что будет лучше. Дело в том, что "область команд" (проще говоря список) исполняемых команд движком, имеет свои локальные переменные на которые она может указывать, путем перечисления их ID. Т.к. таких областей у меня может быть много, то проще разбивать области хранения под задачи, для которых они предназначены (как например, стек для временных переменных во время исполнения команды). Вдобавок, делать описанное вами будет излишне, т.к. у меня происходят обработка не только операции +, /, и т.д., а еще и операция присвоения. Тогда совсем логично, что ни ID, ни имя у временной переменной нет и быть не должно, а при присвоении ее значения присваиваемой переменной, остается только переменная, которой присвоили. Поэтому, ни операторы +, / и т.д., ни контроль ID мне внутри класса не нужен. Тем более, что проще объединить константные значения, переменные, временные переменные в один класс, т.к. по сути они одинаковы в своих значениях, а большего при операции над ними не требуется. З.Ы. Можеть я не так понял смысл вашего поста, но по мне вы начали думать о интерпретаторах, что несколько выходит за рамки темы. ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 15:48 Не спорю, что всего заранее не предусмотреть. Но, "заложить фундамент" я понимаю как некий основной теор. минимум: как вообще другие с подобными проблемами справлялись, есть ли отточенные решения для этой ситуации, какие инструменты ит.д. Я тоже продумываю все на листке бумаги, но всегда знаю, что может получиться криво. Ибо вначале, никак без этого, всегда где-нибудь не хватить знаний или опыта. ;) Но вот иерархия для класса NNumeric у меня вышла такая, какая она есть. И я не нашел пока причин ее переделывать иначе, мне пока этого варианта хватает. Все остальное подчиненно именно постановке задачи и того, что требуется. Т.е., если написаны переопределенные операторы, значит при исходном (без них) варианте, они мне понадобились, чтобы сохранить исходный вариант записи при добавлении операций с "*". Все, как учил дядька Страустрап. ;)И под архитектурой я вовсе не имею ввиду окончательный вариант, но некий интерплей между объектами, их обязанности, иерархия, какие то свойства основные.. Короче, хотел выразить мысль, что картина вырисовывается не из-за понятий, а из взаимоотношений между ними.. Как то так)) К тому же, хуже от того, чтобы вначале подумать, взять листочек с ручкой, почеркать, походить, покурить точно не будет) (разве что от покурить))) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 16:07 Не спорю, что всего заранее не предусмотреть. Но, "заложить фундамент" я понимаю как некий основной теор. минимум: как вообще другие с подобными проблемами справлялись, есть ли отточенные решения для этой ситуации, какие инструменты ит.д. Хммм.. ну как сказать, "дело тонкое". Мне часто приходится делать задачи которые имеют аналоги, т.е. уже не раз делались. Но это совсем не Assistant где уже готовые/отточенные решения. Конечно, всегда хочется "прикрутить готовое" - но вот получается редко :) Смотришь - вроде исходники (часто open-source) грамотные, ладно, рискну. А через неделю-две начинаешь понимать что (несмотря на "формальную грамотность") программист тупенько передрал такую-то статью. А что оно работает "до первого милиционера", что никакие граничные случаи не отрабатываются, да и вообще сам алгоритм слабоват - так его это не волновало. Чтобы не быть голословным, вот примерчик (Вы templae любите)http://www.csie.ntu.edu.tw/~cyy/courses/rendering/pbrt-2.00/html/octree_8h_source.html (http://www.csie.ntu.edu.tw/~cyy/courses/rendering/pbrt-2.00/html/octree_8h_source.html) Где с первого взгляда все гладко/хорошо - но это не так Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 07, 2011, 16:10 Не спорю, что всего заранее не предусмотреть. Но, "заложить фундамент" я понимаю как некий основной теор. минимум: как вообще другие с подобными проблемами справлялись, есть ли отточенные решения для этой ситуации, какие инструменты ит.д. Я тоже продумываю все на листке бумаги, но всегда знаю, что может получиться криво. Ибо вначале, никак без этого, всегда где-нибудь не хватить знаний или опыта. ;) Но вот иерархия для класса NNumeric у меня вышла такая, какая она есть. И я не нашел пока причин ее переделывать иначе, мне пока этого варианта хватает. Все остальное подчиненно именно постановке задачи и того, что требуется. Т.е., если написаны переопределенные операторы, значит при исходном (без них) варианте, они мне понадобились, чтобы сохранить исходный вариант записи при добавлении операций с "*". Все, как учил дядька Страустрап. ;)И под архитектурой я вовсе не имею ввиду окончательный вариант, но некий интерплей между объектами, их обязанности, иерархия, какие то свойства основные.. Короче, хотел выразить мысль, что картина вырисовывается не из-за понятий, а из взаимоотношений между ними.. Как то так)) К тому же, хуже от того, чтобы вначале подумать, взять листочек с ручкой, почеркать, походить, покурить точно не будет) (разве что от покурить))) Я хочу сказать, что нужно учится выбирать правильные решения, а не решения, которые направлены на обход граблей. Я тоже согласен с brankovic, что введение таких сомнительных операторов только запутывают логику и программу - это грабли, на которые кто-нить да наступит.. А можно, если не сложно, описать для чего всё это нужно и как по Вашему это всё работает и почему это должно быть именно так? Вобщем описание проблемы не могли бы изложить? Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 07, 2011, 16:19 Не спорю, что всего заранее не предусмотреть. Но, "заложить фундамент" я понимаю как некий основной теор. минимум: как вообще другие с подобными проблемами справлялись, есть ли отточенные решения для этой ситуации, какие инструменты ит.д. Хммм.. ну как сказать, "дело тонкое". Мне часто приходится делать задачи которые имеют аналоги, т.е. уже не раз делались. Но это совсем не Assistant где уже готовые/отточенные решения. Конечно, всегда хочется "прикрутить готовое" - но вот получается редко :) Смотришь - вроде исходники (часто open-source) грамотные, ладно, рискну. А через неделю-две начинаешь понимать что (несмотря на "формальную грамотность") программист тупенько передрал такую-то статью. А что оно работает "до первого милиционера", что никакие граничные случаи не отрабатываются, да и вообще сам алгоритм слабоват - так его это не волновало. Чтобы не быть голословным, вот примерчик (Вы templae любите)http://www.csie.ntu.edu.tw/~cyy/courses/rendering/pbrt-2.00/html/octree_8h_source.html (http://www.csie.ntu.edu.tw/~cyy/courses/rendering/pbrt-2.00/html/octree_8h_source.html) Где с первого взгляда все гладко/хорошо - но это не так Я бы не стал это использовать.. Я всегда с большим подозрением отношусь к подобным конструкциям: Код Когда вот так просто открытые указатели объявляют.. Это не в традициях C++ хотя впрочем этот класс у них явно нигде не пресутствует.. Не знаю, тут разбираться надо.. Просто это первое, что в глаза попало.. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 16:22 но по своему опыту знаю, что отношусь к тем людям, у которых понимание опережает формулирование мыслей. Из-за этого иногда возникают не состыковки. Насколько могу судить о себе, я принадлежу к именно такому типу людей :) Но как ни крути, а задачу формулировать надо. Вы же даете/публикуете только свои выводы, они могут быть верны или нет, но совершенно непонятно к какой задаче/цели они относятся :)Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 16:47 Когда вот так просто открытые указатели объявляют.. Ну то "дело вкуса". Я спокойно отношусь к открытым членам класса, если Вы нет - никто не мешает сделать это private, код-то открыт. А вот принципиально что эта реализация (как и многие др) имеет жестокие пробои в ф-циональности и, по существу, пригодна лишь для студенческого курсового (так, абы було, отчитаться)Это не в традициях C++ хотя впрочем этот класс у них явно нигде не пресутствует.. Не знаю, тут разбираться надо.. Просто это первое, что в глаза попало.. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 07, 2011, 17:08 brankovic, спасибо, но я уже это понял, когда вы намекнули про утечку (этот момент я тоже исправил), поэтому там, где у себя лишним поставил деструктор для dt, его же и убрал. Работу с указателями привел потому, что вы спрашивали. Хотелось бы увидеть не саму работу с указателями а место, где она обязательно необходима. Вот, например, я храню std::vectror <NNumeric *> stack; я могу вместо этого спокойно использовать std::vector <NNumeric> stack; Но пусть даже будет NNuberic *, тогда функцию pop () можно написать примерно так: Код
не хочется навязываться со своим мнением, но я всё же не понимаю, что удобного в указателях. ИМХО лучше обойтись без них, чем создавать путаницу всякими операторами (а перегрузка операторов и конструкторы от нетривиальных агрументов это всегда путаница). То есть вопрос такой: по какой причине для NNumeric вообще нужно хоть раз использовать оператор new? Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 17:18 Вот, например, я храню Если Eten связался с ID и "уникальностью" экземпляров - то нет, практически он вынужден работать по указателю. Конечно не беда, но зачем создавать причудливые конструкции? std::vectror <NNumeric *> stack; я могу вместо этого спокойно использовать std::vector <NNumeric> stack; Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 17:50 Не думаете ли Вы, что задуманная Вами архитектура единствена? Единственная врятли, т.к. идея всегда одна, вариантов море. Надо только понимать, что выбрав один вариант, как основную линию, всегда практичней ее придерживаться, нежели брать обрывки из различных вариантов. Попытка взять все самое лучшее из других вариантов, по сути еще один вариант. ;) Я хочу сказать, что нужно учится выбирать правильные решения, а не решения, которые направлены на обход граблей. Я тоже согласен с brankovic, что введение таких сомнительных операторов только запутывают логику и программу - это грабли, на которые кто-нить да наступит.. А можно, если не сложно, описать для чего всё это нужно и как по Вашему это всё работает и почему это должно быть именно так? Вобщем описание проблемы не могли бы изложить? Насчет сомнительных операторов со "*", сомнения отпадают, когда приходится работать с указателями для хранения объектов, через базовые. Ситуации, где бы я мог передать указателю адрес из стека и рулить им в указателе на базовый класс я не встречал, а учитывая, что объект в программе используется только одним способом (вариантом), то для способов он не подходит. Полагаю, что именно абзацем ниже стоит объяснить почему. Для начало повторюсь, что класс NNumeric (ровно как и другие) чисто хранит в себе значение и дополнительную информацию нужную движку-исполнителю. Который в свою очередь обеспечивает работу с такими типами данных, как NNumeric. Т.е. движок - это исполнитель входного кода в виде команд. Он осуществляет операции с экземплярами NNumeric и хранит из в виде указателей на базовый класс. Базовые классы используются не только для хранения, но для группирования классов по иерархии, т.к. есть классы сложнее NNumeric и использующие его для хранения чисел. Т.к. класс NNumeric используется для хранения и конструктор копирования по ссылке и также оператор присваивания по умолчанию копируют члены из экземпляра одного в другой, то намного практичнее было сделать класс NNumeric именно принимающим значения, а не выполняющим переопределенные операторы для арифметики. Т.к. он спокойно может выдать свое значение с учетом типа, в который преобразуется. А дальше обычные действия. Т.к. в основном операции идут, через тип double и не могут пересечь ее границ (из-за границ установленных в классе, так и из-за границ самого типа float, т.к. получаем числа из файлов в виде 4 байт), то удобней применять его в качестве параметра автоматического конструктора и осуществлять контроль границ уже внутри класса. Сами типы float и qint32 также выдаются, но чисто для записи в файл или на вывод, но qint32 также используется в целочисленных операциях вместо double. Естественно для контроля целое/не целое есть _isreal, с помощью которого движок осуществляет правильное преобразование значений в нужный тип данных. Т.о. преобладает использование класса NNumeric без указателя. Но, т.к. нигде не было встречено работы базовых классов с производными без указатели в СИ++, то необходимо использовать указатели на базовый класс. Но указатели на базовый класс приводятся к указателям на класс NNumeric, а переопределенные операторы (т.е. те, что имеют в классе) и работают с экземпляром NNumeric, а не указателем на класс NNumeric. Поэтому потребовалось сохранить работу с экземплярами NNumeric, а указатели использовать только чисто для хранения, но оперировать только лишь экземплярами NNumeric. Тем более, что передавая т.о., как описано в классе NNumeric мы не трогаем хранящиеся переменные, константные значения и временные переменные (хотя эти врятли, т.к. они попадают только в QStack). Т.к. при таком подходе обрывается связь с тем место, откуда был взят экземпляр, как если бы я работал через QVariant. А мне именно это и нужно, чтобы не затрагивать место хранения. С другой стороны, просто так указателю на класс не присвоишь экземпляр класса, т.к. работать с указателем ссылающимся на экземпляр класса объявленного не в куче, а в стеке вызывает очевидные проблемы. Следовательно, нужно по отдельно использовать все set функции для передачи хранящейся информации из экземпляра в указатель на класса, предварительно вызвав конструктор для указателя на класс. Этот указатель мы и сохраняем в указатель на базовый класс. Получается следующая ситуация, у нас много операций с экземплярами и нам придется повторить такое же кол-во раз, сколько и самих экземпляров используется, отсюда могут полезть ошибки и получится использование одного и того же кода два и более раз. Поэтому, практичнее сократить форму записи прописав все это в преобразование в NNumeric*, т.к. при наличии подобного переопределенного оператора он используется при попытке экземпляр класса присвоить указателю на этот класс или базовый для него. Т.о. мне практически ничего не надо было переписывать в функции матем. операций. Но одна сторона медали, а теперь другая. Т.к. для вывода и прочих операций опять используются только экземпляры класса NNumeric, то и здесь указатели не нужны. Но, хранится то у нас это все в указателях на базовый класс и даже после приведения к классу, это опять же указатель на класс, а нам нужны экземпляры. Опять же возникнет многократное вызывание функций set у класса NNumeric и опять тоже самое, что и в случае с передачей значений из указателя в экземпляр класса. Опять же все это прописываем в классе перегружая конструтор копирования, который по сути просто копирует значения, но внутри себя, и оператор присваивания, который по сути выполняет тоже самое. Но есть одно "но", однако здесь тоже самое, что и с конструктором копирования по ссылке и такому же оператору присвоения. Т.е. в одних случая идет присвоение, в других инициализация. Вот и получается, что таким переопределением определенных операторов и конструкторов я могу спокойно пользоваться экземплярами класса, а при передачи их в место хранения они сами выдадут указатель на класс созданный в куче, а не в стеке. А также при взятии из места хранения мне нет нужды исписывать километры строк для передачи значений в экземпляр класса. При этом не затрагивается как место хранения при работе с указателями, так и сами значения при выполнении операций над экземплярами класса. Говоря иначе, указатели для хранения с использованием базовых классов, ибо без указателей здесь никак. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 17:52 Вот, например, я храню Если Eten связался с ID и "уникальностью" экземпляров - то нет, практически он вынужден работать по указателю. Конечно не беда, но зачем создавать причудливые конструкции? std::vectror <NNumeric *> stack; я могу вместо этого спокойно использовать std::vector <NNumeric> stack; И честно говоря, у меня в программе они так быть использованы, как у вас не могут. Они не для такого применения задуманы. ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 18:02 Ладно, приложу еще одну функцию:
Код
Вопрос, как это (см. код выше) можно записать без применения тех трех макроопределений с NNumeric*, а ведь это только малая часть движка? ;) З.Ы. Честно, я все никак не могу понять, почему вы их называете хаками, ведь я ничего противоестественного не делаю с самими операторами и конструктором, т.е. использую их как по обычному без переопределенний, всего лишь сократил себе лишние строки в коде. ??? Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 07, 2011, 19:36 Честно, я все никак не могу понять, почему вы их называете хаками, ведь я ничего противоестественного не делаю с самими операторами и конструктором, т.е. использую их как по обычному без переопределенний, всего лишь сократил себе лишние строки в коде. ??? Диалог в переполненном автобусеЦитировать - Цигане, посунься будь ласка Если Вы считаете что так Вы "ничего плохого" не делаете, то что ж будет когда сделаете? :)- Я афро-американец, а не цыган - O! То якi в вас мають бути цигани? case 2: Нормальный программист "рефлекторно" стремится записать это одной строкой, напр.dt = this->StackValue.pop(); arg2 = dynamic_cast<NNumeric*>(dt); delete dt; dt = this->StackValue.pop(); arg1 = dynamic_cast<NNumeric*>(dt); delete dt; if (!arg1.IsReal() && !arg2.IsReal()) { arg0.setIsReal(false); arg0.setValue(double(arg1) + double(arg2)); } else arg0 = double(arg1) + double(arg2); this->StackValue.push(arg0); break; Код Где pop_value просто так Код
И еще. Не хотелось начинать неприятный разговор, но приходится. Перлы типа Цитировать case 2: // видимо Вам еще не приходилось "откапывать" это 2 и вспоминать маму написавшего С полным правом могут расцениваться как прямое неуважение к собеседникам и к форуму вообще. Так можно писать "на первенство двора", но не в приличном обществе. Извольте оформить все как положено, иначе - будьте здоровы . .. case 32: StackValie (с большой буквы и совсем не "value") Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 07, 2011, 20:00 Не думаете ли Вы, что задуманная Вами архитектура единствена? Единственная врятли, т.к. идея всегда одна, вариантов море. Надо только понимать, что выбрав один вариант, как основную линию, всегда практичней ее придерживаться, нежели брать обрывки из различных вариантов. Попытка взять все самое лучшее из других вариантов, по сути еще один вариант. ;) Я хочу сказать, что нужно учится выбирать правильные решения, а не решения, которые направлены на обход граблей. Я тоже согласен с brankovic, что введение таких сомнительных операторов только запутывают логику и программу - это грабли, на которые кто-нить да наступит.. А можно, если не сложно, описать для чего всё это нужно и как по Вашему это всё работает и почему это должно быть именно так? Вобщем описание проблемы не могли бы изложить? Насчет сомнительных операторов со "*", сомнения отпадают, когда приходится работать с указателями для хранения объектов, через базовые. Ситуации, где бы я мог передать указателю адрес из стека и рулить им в указателе на базовый класс я не встречал, а учитывая, что объект в программе используется только одним способом (вариантом), то для способов он не подходит. Полагаю, что именно абзацем ниже стоит объяснить почему. Для начало повторюсь, что класс NNumeric (ровно как и другие) чисто хранит в себе значение и дополнительную информацию нужную движку-исполнителю. Который в свою очередь обеспечивает работу с такими типами данных, как NNumeric. Т.е. движок - это исполнитель входного кода в виде команд. Он осуществляет операции с экземплярами NNumeric и хранит из в виде указателей на базовый класс. Базовые классы используются не только для хранения, но для группирования классов по иерархии, т.к. есть классы сложнее NNumeric и использующие его для хранения чисел. Т.к. класс NNumeric используется для хранения и конструктор копирования по ссылке и также оператор присваивания по умолчанию копируют члены из экземпляра одного в другой, то намного практичнее было сделать класс NNumeric именно принимающим значения, а не выполняющим переопределенные операторы для арифметики. Т.к. он спокойно может выдать свое значение с учетом типа, в который преобразуется. А дальше обычные действия. Т.к. в основном операции идут, через тип double и не могут пересечь ее границ (из-за границ установленных в классе, так и из-за границ самого типа float, т.к. получаем числа из файлов в виде 4 байт), то удобней применять его в качестве параметра автоматического конструктора и осуществлять контроль границ уже внутри класса. Сами типы float и qint32 также выдаются, но чисто для записи в файл или на вывод, но qint32 также используется в целочисленных операциях вместо double. Естественно для контроля целое/не целое есть _isreal, с помощью которого движок осуществляет правильное преобразование значений в нужный тип данных. Т.о. преобладает использование класса NNumeric без указателя. Но, т.к. нигде не было встречено работы базовых классов с производными без указатели в СИ++, то необходимо использовать указатели на базовый класс. Но указатели на базовый класс приводятся к указателям на класс NNumeric, а переопределенные операторы (т.е. те, что имеют в классе) и работают с экземпляром NNumeric, а не указателем на класс NNumeric. Поэтому потребовалось сохранить работу с экземплярами NNumeric, а указатели использовать только чисто для хранения, но оперировать только лишь экземплярами NNumeric. Тем более, что передавая т.о., как описано в классе NNumeric мы не трогаем хранящиеся переменные, константные значения и временные переменные (хотя эти врятли, т.к. они попадают только в QStack). Т.к. при таком подходе обрывается связь с тем место, откуда был взят экземпляр, как если бы я работал через QVariant. А мне именно это и нужно, чтобы не затрагивать место хранения. С другой стороны, просто так указателю на класс не присвоишь экземпляр класса, т.к. работать с указателем ссылающимся на экземпляр класса объявленного не в куче, а в стеке вызывает очевидные проблемы. Следовательно, нужно по отдельно использовать все set функции для передачи хранящейся информации из экземпляра в указатель на класса, предварительно вызвав конструктор для указателя на класс. Этот указатель мы и сохраняем в указатель на базовый класс. Получается следующая ситуация, у нас много операций с экземплярами и нам придется повторить такое же кол-во раз, сколько и самих экземпляров используется, отсюда могут полезть ошибки и получится использование одного и того же кода два и более раз. Поэтому, практичнее сократить форму записи прописав все это в преобразование в NNumeric*, т.к. при наличии подобного переопределенного оператора он используется при попытке экземпляр класса присвоить указателю на этот класс или базовый для него. Т.о. мне практически ничего не надо было переписывать в функции матем. операций. Но одна сторона медали, а теперь другая. Т.к. для вывода и прочих операций опять используются только экземпляры класса NNumeric, то и здесь указатели не нужны. Но, хранится то у нас это все в указателях на базовый класс и даже после приведения к классу, это опять же указатель на класс, а нам нужны экземпляры. Опять же возникнет многократное вызывание функций set у класса NNumeric и опять тоже самое, что и в случае с передачей значений из указателя в экземпляр класса. Опять же все это прописываем в классе перегружая конструтор копирования, который по сути просто копирует значения, но внутри себя, и оператор присваивания, который по сути выполняет тоже самое. Но есть одно "но", однако здесь тоже самое, что и с конструктором копирования по ссылке и такому же оператору присвоения. Т.е. в одних случая идет присвоение, в других инициализация. Вот и получается, что таким переопределением определенных операторов и конструкторов я могу спокойно пользоваться экземплярами класса, а при передачи их в место хранения они сами выдадут указатель на класс созданный в куче, а не в стеке. А также при взятии из места хранения мне нет нужды исписывать километры строк для передачи значений в экземпляр класса. При этом не затрагивается как место хранения при работе с указателями, так и сами значения при выполнении операций над экземплярами класса. Говоря иначе, указатели для хранения с использованием базовых классов, ибо без указателей здесь никак. Лучше опишите суть задачи, которую Вы пытаетесь реализовать.. (как можно проще и понятнее, на пальцах можно сказать) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 07, 2011, 23:05 case 2: Нормальный программист "рефлекторно" стремится записать это одной строкой, напр.dt = this->StackValue.pop(); arg2 = dynamic_cast<NNumeric*>(dt); delete dt; dt = this->StackValue.pop(); arg1 = dynamic_cast<NNumeric*>(dt); delete dt; if (!arg1.IsReal() && !arg2.IsReal()) { arg0.setIsReal(false); arg0.setValue(double(arg1) + double(arg2)); } else arg0 = double(arg1) + double(arg2); this->StackValue.push(arg0); break; Код Где pop_value просто так Код
И еще. Не хотелось начинать неприятный разговор, но приходится. Перлы типа Цитировать case 2: // видимо Вам еще не приходилось "откапывать" это 2 и вспоминать маму написавшего С полным правом могут расцениваться как прямое неуважение к собеседникам и к форуму вообще. Так можно писать "на первенство двора", но не в приличном обществе. Извольте оформить все как положено, иначе - будьте здоровы . .. case 32: StackValie (с большой буквы и совсем не "value") Код: Модификатор Комментарий Да, кстати, а почему вы мне все время указывает на то, что я с большой буквы начинаю? В этом нет ничего плохого, т.к. есть два общепринятых стиля. Один из них, который указывали вы и другие, а другой я сам использую. Что-то я не припомню, что был только один стиль. ;) Насчет сократить код до одной строки мысль интересная, но не везде годная. Это я еще в функции MathematicalOperations обработку на особые ситуации не прописывал (надо до этого прописать и реализовать кое-что еще). Например в case 7, это у вас никак не выйдет. Но все равно спасибо. ;) З.Ы. Про автобус рассмешило, но ситуация с хаками для все равно, что вопрос для человека из древности: "Земля вокруг Солнца или Солнце вокруг Земли движется". ::) З.З.Ы. m_ax, я понимаю, что возможно написал сложновато или увлекся, но сегодня уже никак, давайте завтра. Утро, вечера мудренее. ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 08, 2011, 00:01 всего лишь сократил себе лишние строки в коде. Это как раз согласен, тоже не люблю лишнего писать. Но этот конструктор со * ничего не сокращает, а только усложняет. Вот есть три строки: Код
их можно переписать так (безо всякого NNumeric(NNumeric*)): Код
одну звёздочку добавил, 2 строчки убрал. А по-хорошему надо вынести в отдельную функцию, как Igors и советовал и везде вместо троек этих страшных останется: Код
Тут можно будет и проверку на тип организовать, и на пустой стек, и всё в одном месте. А так, как сейчас, чуть в стеке что не то попадётся и всё, access violation. Edit: речь не о том, что конструктор NNumeric (NNumeric *) "неправильный", потому что его нет в книжке или ещё что-то. Речь о том, что он не приносит пользы. Я не против извращений как таковых, я против извращений от которых нет никакого удовольствия. Edit: код номер 2 конечно бред, хорошо, что Eten меня понял и так :) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 08, 2011, 07:12 brankovic, вот так бы сразу и сказали. ;) Я, честно говоря, помню о работе с указателями, но что-то восприятие надо мной шутку сыграло. ::) Да, конструктор действительно оказался уже не нужен (в классе его убрал), а вот и та функция (пока она будет без дополнительных проверок, это буду писать позднее), о которой вы говорили:
Код: NNumeric NEngine::PopNumeric() Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 08, 2011, 07:56 В общем спасибо всем за помощь, есть чему поучиться у других. :)
А также обещанное про краткое описание задачи. Задача тут следующая. Мне нужно производить работу над значениями NNumeric, в одних случаях через функции типа get/set, в других случаях через операторы преобразования и конструкторы для удобной формы записи, определенного контроля над значениями внутри класса и сокращения кода, чтобы вся работа производилась только через экземпляры класса. А этих экземпляров класса NNumeric, учитывая что исполнитель - это сути своей автомат и работу он производит автоматически, используется, при операциях с ними, достаточно мало. Только хранение в памяти они в виде экземпляров могут занимать много места (в чем-то могу здесь ошибаться, но как ни крути, а с указателями по части хранения и работы с памятью будет проще и быстрее). Т.о. нужно реализовать класс NNumeric так, чтобы можно было, спрятав работу экземпляра класса с указателем на класс, использовать экземпляр этого класса везде, где это необходимо. Т.е. сохранить работу с классом NNumeric в программе, в виде работы с экземплярами класса NNumeric. ИМХО, так проще для моей программы, а заодно можно спокойно пользоваться базовыми классами (и ляпов не сделать где-нибудь, т.е. класс сам контролирует передачу данных, т.к. это и есть его основная задача) не сильно изменяя сам код программы (по сути дела там произошли всего лишь небольшие изменения, а не переписывание всего кода или его большой части). Просто примите тот факт, что класс NNumeric предназначен чисто для контроля передачи данных, которых он в себе хранит. А все прочие операции над его числовым значением выполняются уже вне самого объекта, т.е. не являются его задачей. Тем более, что для движка-исполнителя (как автомата) такой вариант класса NNumeric наиболее подходящий и практичный. Будь у меня чисто операции над определенным форматом чисел, как например, комплексные числа, я бы написал сам класс NNumeric иначе. З.Ы. Еще проще я написать не смогу и не хотелось бы больше возвращаться к этому, т.к. я уже почти все разобрал в этой теме. Остался только вопрос "Динамическая информация о типе" (сейчас над этим работаю). Это единственное, что осталось у меня. Заранее хочу сказать, что у меня и в мыслях нету никого обижать, но если мы будем обсуждать класс NNumeric дальше, то эта тема начнет отнимать у меня время, которое я хочу потратить на свой проект. Если уж вас сильно стало интересовать чем я занимаюсь, то напишите мне в личку, дам вам ссылку на сайт с информацией, но не гарантирую что она вам будет понятна (там хранится мой черновик). ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: lenny от Март 08, 2011, 12:21 никакие dynamic_cast и typeid работать не будут, т.к. именно код конструктора прописывает/заполняет Можно поподробнее? Или ссылку на материал описывающий данный процесс.Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 08, 2011, 15:41 Перечитал Бьерна и поискал информацию по typeid (http://www.cplusplus.com/reference/std/typeinfo/type_info/). В общем, проверка на совпадение производным классом, указателя на базовый класс, для меня вышла такой (в функции Writeln, см. ответ 15 (http://www.prog.org.ru/index.php?topic=17062.msg114431#msg114431)):
Код: if (typeid(NNumeric) == typeid(*dt)) { Соответственно строка с "#include <typeinfo>" стоит на положенном месте. ;) До этого она была такой: Код: if (dynamic_cast<NNumeric*>(dt) != NULL) { Больше вопросов по этой теме не имею. ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 08, 2011, 15:43 никакие dynamic_cast и typeid работать не будут, т.к. именно код конструктора прописывает/заполняет Можно поподробнее? Или ссылку на материал описывающий данный процесс.А вообще, насколько я знаю, формат RTTI закрыт, т.е. каждый компилятор может реализовывать как ему хочется - разумно. Как я понял (балуясь/экспериментируя в свободное от работы время в отладчике), RTTI хранит 2 значения: 1) указатель на сам объект 2) смещение данного типа от начала объекта В связи с этим Код Эта ф-ция может вернуть не NULL Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 08, 2011, 16:16 Eten, я вовсе не сторонник "формального" подхода и "чеканного следования прынцыпам ООП" - скорее наоборот. Но "всему же есть границы" как писал классик. А Вы их попираете/насилуете на каждом шагу. Ну вот например
Код
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 08, 2011, 16:31 Igors, применение IsReal, как и их запись, через setIsReal мне нужна при работе движка с NNumeric. Здесь же, есть момент, когда мне необходимо делать вызовы set-функций для записи целых чисел. А применение IsReal в условии это то, что необходимо движку при его работе. Честно, я не нашел способа короче. ;)
З.Ы. Смотря, что прятать в классе. ;) З.Ы. Да, кстати подобные вызовы стоят у меня не где попало, а где это необходимо (например в функции мат. операций, логики и работы со строками, а также при записи переменных в память). ИМХО, класс достаточно инкапсулирован в соответствии с той задачей, для которой он был создан. ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 08, 2011, 17:30 Да, кстати подобные вызовы стоят у меня не где попало, а где это необходимо (например в функции мат. операций, логики и работы со строками, а также при записи переменных в память). ИМХО, класс достаточно инкапсулирован в соответствии с той задачей, для которой он был создан. ;) Ой, ну вот не надо прятаться за специфику задачи и рассказывать сказки "про белого бычка" :) Вопрос о "типе результата" прекрасно решается на уровне класса, напр.Код Я не помню точно имена членов класса - но не суть Edit: да и вообще по-хорошему метод IsReal должен быть private Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 08, 2011, 17:40 Ладно, убедили.
Но скажу сразу, что не подумал как-то об этом, изначально код то у меня был другой (т.е. явно не было видно). И постоянно что-то переписывая, можно и не заметить, как придешь к такому. ::) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 08, 2011, 18:10 brankovic, вот так бы сразу и сказали. ;) Я, честно говоря, помню о работе с указателями, но что-то восприятие надо мной шутку сыграло. ::) Да, конструктор действительно оказался уже не нужен (в классе его убрал), а вот и та функция (пока она будет без дополнительных проверок, это буду писать позднее), о которой вы говорили: А зачем здесь dt удалять?? Или так задумано, что при каждом вызове PopNumeric удалять очередной элемент в StackValue? Это не хорошо..Код: NNumeric NEngine::PopNumeric() Короче полный даркнэсс, как говорит один мой знакомый) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 08, 2011, 18:36 Код: NNumeric NEngine::PopNumeric() Короче полный даркнэсс, как говорит один мой знакомый) Код Зачем же так "серпом по нежному месту"? Если имя не придумалось, просто доливаете артикль, напр Код Просто и со вкусом Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 08, 2011, 18:47 Цитировать Ну почему нехорошо? "pop" предполагает что ответственность за "снятый" элемент возьмет на себя кто-то другой, может и удалить, это нормально. В смысле? Возвращает же функция не указатель... Даже если бы и указатель, то delete dt порушит весь объект к чёрту.. Т.е. попробуйте вызвать эту функцию дважды PopNumeric() интересно, что получится) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 08, 2011, 19:27 Цитировать Ну почему нехорошо? "pop" предполагает что ответственность за "снятый" элемент возьмет на себя кто-то другой, может и удалить, это нормально. В смысле? Возвращает же функция не указатель... Даже если бы и указатель, то delete dt порушит весь объект к чёрту.. Т.е. попробуйте вызвать эту функцию дважды PopNumeric() интересно, что получится) Цитировать - Нет-нет, я не туда попал (глупые стихи случайно застрявшие в памяти :)) - Да как же не туда - да именно сюда "pop" снимает из очереди LIFO (стек) но ничего не обещает об удалении. Последовательный вызов 2 и более pop приведет к снятию 2 и более тех кто был на стеке - это нормально. Конечно Вы это знаете, просто заработались/заскок :) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 08, 2011, 19:44 Короче полный даркнэсс, как говорит один мой знакомый) Просто Eten на тёмной стороне силы. Но это не значит, что он не станет великим программистом ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 09, 2011, 07:06 Фух, только что переписал до конца (разумеется выспавшись ;) ) на стиль Си++ оформление везде в своей проге, плюс сделал полную инкапсуляцию класса NNumeric. Заодно, оказалось, что проблем при работе с местом хранения (т.е. запись в места хранения) полная инкапсуляция мне не создает. Плюс ко всему этому, обеспечил класс NNumeric статическими математическими функциями, которые для него допустимы исходя из ТЗ программы. Т.е. работает, как и раньше, только код стал удобным, читабельным и компактным.
Базовые классы для NNumeric: Код
Сам класс NNuemric: Код
Функция мат. операций: Код
Код
Полагаю, что еще лучше не упрячешь. А инкремент и декремент, операции исключительного рода, поэтому их никак не свернуть и там они еще требует выполнение записи обратно (пока не реализовал). З.Ы. Мне уже скоро NNuemric сниться начнут. ::) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 09, 2011, 12:25 Фух, только что переписал до конца (разумеется выспавшись ;) ) Должны, это нормально когда программист работает над задачей... З.Ы. Мне уже скоро NNuemric сниться начнут. ::) Переписали - намного лучше, но все равно, еще очень "рыхло" (как в ранних романах Бальзака). NSimpleDataTypes() : NDataTypes() {_constValue = false;} Дефаулт конструктор базового класса сам вызовется, поэтому упоминать его не нужноcase 2: Так писать западло, Вы создаете кучу потенциальных проблем. Есть просто enum, его можно освоить за 5-10 минут. Закоренелые С-шники предпочитают #define - тоже приемлемо но НИКОГДА не должно проходить "просто число"с id и name нужно разбираться, здесь требуется постановка Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 09, 2011, 13:08 NSimpleDataTypes() : NDataTypes() {_constValue = false;} Дефаулт конструктор базового класса сам вызовется, поэтому упоминать его не нужноcase 2: Так писать западло, Вы создаете кучу потенциальных проблем. Есть просто enum, его можно освоить за 5-10 минут. Закоренелые С-шники предпочитают #define - тоже приемлемо но НИКОГДА не должно проходить "просто число"с id и name нужно разбираться, здесь требуется постановка Насчет case у меня идет формирование команд и их модификаторов, но да, позднее у меня конечно будет сформированно перечисление модификатор, как в Qt есть (не помню точно какой, голова сейчас другим забита), т.к. определение модификатора для команд у меня будет одно единственное. Но думаю, что действительно уже пора его написать. Насчет id и name это вы правы, но для этого мне еще нужно воссоздать некоторое кол-во классов, чтобы постановка приобрела более четкую картину представления и ее можно было бы дать прочесть другим. Но на это потребуется не мало времени. Переписали - намного лучше, но все равно, еще очень "рыхло" (как в ранних романах Бальзака). А можете подсказать, в чем рыхловатость? Щас я не смогу увидеть всей рыхловатости, т.к. создаю поэтапно, но зная направление своего проекта. И при построении других классов и применения этого, я смогу заметить что-то и исправить (с напильником в руках) найденный недочет. Но некоторые подсказки, даже навскидку могут подсказать мне направления, с помощью которых я смогу увидеть то, чего можеть быть и не смог. Или то, о чем мог и не подозревать. ;) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 09, 2011, 13:42 А можете подсказать, в чем рыхловатость? лучшее враг хорошего. Для вашего уровня всё отлично. Понимание тонкостей придёт с опытом P.S.: если Igors сказал всего лишь рыхловатый, то в моём представлении это где-то между 4+ и 5- :) Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Eten от Март 09, 2011, 14:03 а-а-а-а, а то я уже подумал много чего. Но теперь буду заранее помнить, что если сначала (при первом представлении класса) не вышло, еще не значит, что потом не смогу инкапсулировать. Т.е. сначало у меня это не получалось, т.к. зашел немного не с той стороны, но в итоге все равно добился желаемого. ;)
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: _govorilka от Март 10, 2011, 08:25 Насчет id и name это вы правы, но для этого мне еще нужно воссоздать некоторое кол-во классов, чтобы постановка приобрела более четкую картину представления и ее можно было бы дать прочесть другим. Но на это потребуется не мало времени. Код: QHash<int, QString> idToName; В чем сложность?.. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: _govorilka от Март 10, 2011, 08:32 Если в класс NDataTypes добавишь виртуальную функцию:
Код
То вот этот кусок кода: Код
Сможешь переписать так: Код
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: voral от Март 10, 2011, 09:49 Не совсем по теме, но:
а) "this->" - так пишут на жабе, а здесь - ну можно, но если Вы хотите что-то подчеркнуть, а не просто так Я то же так пишу. Цель: выделить то, что относится к классу от каких то "локальных" переменных. Можно сказать на всякий случай, что б потом если придется вернуться к коду через некий промежуток времени незадумыватьсяНазвание: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 10, 2011, 10:07 ИМХО, ненужное засорение кода.
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Igors от Март 10, 2011, 11:00 А можете подсказать, в чем рыхловатость? Ну вот напримерif (typeid(NNumeric) == typeid(*dt)) { NNumeric numeric = *dynamic_cast<NNumeric*>(dt); str = QString(numeric); } if (typeid(NString) == typeid(*dt)) { NString string = *dynamic_cast<NString*>(dt); str = string.value(); } - зачем привлекать и typeid и еще dynamic_cast? Это вещи разные, здесь лучше обойтись одной, - добавить else чтобы код не гонял воздух, если к одному типу привелись, другие приведения уже ни к чему проверять - неясно зачем нужно возвращать numeric по значению, чем не устраивает просто указатель для получения строки? - согласен с _govorilka что иметь метод типа toString гораздо проще/естественнее (может и обобщить удастся). Конструктор QString(numeric) не вызывается необходимостью - если цель вернуть строку, то менять объекты мы не собираемся, значит это надо подчеркнуть словом const Поэтому поприятнее так Код Или, как указал _govorilka , сделать toString методом базового класса тогда вместо ветвистого else всего одна проверка Код Пусть не критично/обязательно, но в этом есть смысл. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 10, 2011, 11:04 ИМХО, ненужное засорение кода. Я тож так не пишу, ноМогу привести одну ситуацию, где так писать целесообразно: Например у нас есть некоторый класс, который имеет закрытую переменную, назовём её value: Код
Однако у меня такое исключено, поскольку перед закрытыми переменными ставлю _ Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 10, 2011, 11:10 Или, как указал _govorilka , сделать toString методом базового класса тогда вместо ветвистого else всего одна проверка Так даже более того, не нужно будет делать никакого приведения, поскольку toString() будет относится к интерфейсу. Код Пусть не критично/обязательно, но в этом есть смысл. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: brankovic от Март 10, 2011, 11:16 Однако у меня такое исключено, поскольку перед закрытыми переменными ставлю _ не рекомендуется стандартом, имена с _ и __ зараезервированы для стандартной библиотеки. Поля класса называю на m, типа m_name. Некоторые ставят _ в конце имени: name_. ИМХО любой способ лучше, чем this->. Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Пантер от Март 10, 2011, 12:02 Согласен с brankovic, ставлю после имени _. Перед именем не рекомендуют ставить _ из-за возможной коллизии имен с макросами.
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: Авварон от Март 10, 2011, 12:26 пишу через d_ptr-_-
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: _govorilka от Март 10, 2011, 12:30 С функцией в базовом классе можно переписать и без dynamic_cast:
Код
Название: Re: Как узнать о типе, до выполнения dynamic_cast? Отправлено: m_ax от Март 10, 2011, 12:32 Однако у меня такое исключено, поскольку перед закрытыми переменными ставлю _ не рекомендуется стандартом, имена с _ и __ зараезервированы для стандартной библиотеки. Поля класса называю на m, типа m_name. Некоторые ставят _ в конце имени: name_. ИМХО любой способ лучше, чем this->. Согласен с brankovic, ставлю после имени _. Перед именем не рекомендуют ставить _ из-за возможной коллизии имен с макросами. Вот ведь, век живи - век учись)) Всё, перехожу обратно на m_ |