Russian Qt Forum
Ноябрь 24, 2024, 03:33 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 3 [4] 5 6   Вниз
  Печать  
Автор Тема: Как узнать о типе, до выполнения dynamic_cast?  (Прочитано 34495 раз)
brankovic
Гость
« Ответ #45 : Март 08, 2011, 00:01 »

всего лишь сократил себе лишние строки в коде.

Это как раз согласен, тоже не люблю лишнего писать. Но этот конструктор со * ничего не сокращает, а только усложняет. Вот есть три строки:

Код
C++ (Qt)
dt = this->StackValue.pop();
arg1 = dynamic_cast<NNumeric*>(dt);
delete dt;
 

их можно переписать так (безо всякого NNumeric(NNumeric*)):

Код
C++ (Qt)
arg1 = *dynamic_cast<NNumeric*>(this->StackValue.pop());
 

одну звёздочку добавил, 2 строчки убрал. А по-хорошему надо вынести в отдельную функцию, как Igors и советовал и везде вместо троек этих страшных останется:

Код
C++ (Qt)
  arg1 = pop_value ();
 

Тут можно будет и проверку на тип организовать, и на пустой стек, и всё в одном месте. А так, как сейчас, чуть в стеке что не то попадётся и всё, access violation.

Edit: речь не о том, что конструктор NNumeric (NNumeric *) "неправильный", потому что его нет в книжке или ещё что-то. Речь о том, что он не приносит пользы. Я не против извращений как таковых, я против извращений от которых нет никакого удовольствия.

Edit: код номер 2 конечно бред, хорошо, что Eten меня понял и так Улыбающийся
« Последнее редактирование: Март 08, 2011, 10:38 от brankovic » Записан
Eten
Гость
« Ответ #46 : Март 08, 2011, 07:12 »

brankovic, вот так бы сразу и сказали.  Подмигивающий Я, честно говоря, помню о работе с указателями, но что-то восприятие надо мной шутку сыграло.  Строит глазки Да, конструктор действительно оказался уже не нужен (в классе его убрал), а вот и та функция (пока она будет без  дополнительных проверок, это буду писать позднее), о которой вы говорили:

Код:
NNumeric NEngine::PopNumeric()
{
    NDataTypes* dt;
    NNumeric arg;
    dt = this->StackValue.pop();
    arg = *dynamic_cast<NNumeric*>(dt);
    delete dt;
    return arg;
}
« Последнее редактирование: Март 08, 2011, 07:13 от Eten » Записан
Eten
Гость
« Ответ #47 : Март 08, 2011, 07:56 »

В общем спасибо всем за помощь, есть чему поучиться у других.  Улыбающийся

А также обещанное про краткое описание задачи. Задача тут следующая. Мне нужно производить работу над значениями NNumeric, в одних случаях через функции типа get/set, в других случаях через операторы преобразования и конструкторы для удобной формы записи, определенного контроля над значениями внутри класса и сокращения кода, чтобы вся работа производилась только через экземпляры класса. А этих экземпляров класса NNumeric, учитывая что исполнитель - это сути своей автомат и работу он производит автоматически, используется, при операциях с ними, достаточно мало. Только хранение в памяти они в виде экземпляров могут занимать много места (в чем-то могу здесь ошибаться, но как ни крути, а с указателями по части хранения и работы с памятью будет проще и быстрее). Т.о. нужно реализовать класс NNumeric так, чтобы можно было, спрятав работу экземпляра класса с указателем на класс, использовать экземпляр этого класса везде, где это необходимо. Т.е. сохранить работу с классом NNumeric в программе, в виде работы с экземплярами класса NNumeric. ИМХО, так проще для моей программы, а заодно можно спокойно пользоваться базовыми классами (и ляпов не сделать где-нибудь, т.е. класс сам контролирует передачу данных, т.к. это и есть его основная задача) не сильно изменяя сам код программы (по сути дела там произошли всего лишь небольшие изменения, а не переписывание всего кода или его большой части).

Просто примите тот факт, что класс NNumeric предназначен чисто для контроля передачи данных, которых он в себе хранит. А все прочие операции над его числовым значением выполняются уже вне самого объекта, т.е. не являются его задачей. Тем более, что для движка-исполнителя (как автомата) такой вариант класса NNumeric наиболее подходящий и практичный. Будь у меня чисто операции над определенным форматом чисел, как например, комплексные числа, я бы написал сам класс NNumeric иначе.

З.Ы.
Еще проще я написать не смогу и не хотелось бы больше возвращаться к этому, т.к. я уже почти все разобрал в этой теме. Остался только вопрос "Динамическая информация о типе" (сейчас над этим работаю). Это единственное, что осталось у меня. Заранее хочу сказать, что у меня и в мыслях нету никого обижать, но если мы будем обсуждать класс NNumeric дальше, то эта тема начнет отнимать у меня время, которое я хочу потратить на свой проект. Если уж вас сильно стало интересовать чем я занимаюсь, то напишите мне в личку, дам вам ссылку на сайт с информацией, но не гарантирую что она вам будет понятна (там хранится мой черновик).  Подмигивающий
« Последнее редактирование: Март 08, 2011, 08:44 от Eten » Записан
lenny
Гость
« Ответ #48 : Март 08, 2011, 12:21 »

никакие dynamic_cast и typeid работать не будут, т.к. именно код конструктора прописывает/заполняет
Можно поподробнее? Или ссылку на материал описывающий данный процесс.
« Последнее редактирование: Март 08, 2011, 12:39 от lenny » Записан
Eten
Гость
« Ответ #49 : Март 08, 2011, 15:41 »

Перечитал Бьерна и поискал информацию по typeid. В общем, проверка на совпадение производным классом, указателя на базовый класс, для меня вышла такой (в функции Writeln, см. ответ 15):
Код:
if (typeid(NNumeric) == typeid(*dt)) {
     NNumeric numeric = *dynamic_cast<NNumeric*>(dt);
     str = QString(numeric);
}

Соответственно строка с "#include <typeinfo>" стоит на положенном месте.  Подмигивающий

До этого она была такой:
Код:
if (dynamic_cast<NNumeric*>(dt) != NULL) {
      NNumeric numeric = dynamic_cast<NNumeric*>(dt);
      str = QString(numeric);
}

Больше вопросов по этой теме не имею.  Подмигивающий
« Последнее редактирование: Март 08, 2011, 15:50 от Eten » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #50 : Март 08, 2011, 15:43 »

никакие dynamic_cast и typeid работать не будут, т.к. именно код конструктора прописывает/заполняет
Можно поподробнее? Или ссылку на материал описывающий данный процесс.
Ну эти познания я почерпнул (довольно давно) из описания "Турбо Паскаль 5.5 (Введение в объектно-ориентированное программирование)"   Улыбающийся

А вообще, насколько я знаю, формат RTTI закрыт, т.е. каждый компилятор может реализовывать как ему хочется - разумно. Как я понял (балуясь/экспериментируя в свободное от работы время в отладчике), RTTI хранит 2 значения:

1) указатель на сам объект
2) смещение данного типа от начала объекта

В связи с этим
Код
C++ (Qt)
class A { int mDataA; };
class B { int mDataB; };
 
B * A2B( A * a )
{
return dynamic_cast <B *> (a);
}
 
Эта ф-ция может вернуть не NULL
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #51 : Март 08, 2011, 16:16 »

Eten, я вовсе не сторонник "формального" подхода и "чеканного следования прынцыпам ООП" - скорее наоборот. Но "всему же есть границы" как писал классик. А Вы их попираете/насилуете на каждом шагу. Ну вот например
Код
C++ (Qt)
           if (!arg1.IsReal() && !arg2.IsReal())
           {
                arg0.setIsReal(false);
                arg0.setValue(double(arg1) + double(arg2));
           }
           else
               arg0 = double(arg1) + double(arg2);
 
Да какого же <..> какая-то ф-ция (посторонка) лезет в детали реализации класса, указывает ему setIsReal и.т..п? Стопудово это сам класс (или его friend операторы) должны решать. Все "потроха" должны быть спрятаны (называется умным словом "инкапсуляция"). Ладно бы еще это один раз (ну сачканул, бывает), но ведь Вы уверенно размножили это для всех операций десятки(!) раз. Я не хочу Вас обидеть, но программирование "через copy/paste" просто унизительно. Работа программиста есть придумывание логических конструкций, а не "долбление".
Записан
Eten
Гость
« Ответ #52 : Март 08, 2011, 16:31 »

Igors, применение IsReal, как и их запись, через setIsReal мне нужна при работе движка с NNumeric. Здесь же, есть момент, когда мне необходимо делать вызовы set-функций для записи целых чисел. А применение IsReal в условии это то, что необходимо движку при его работе. Честно, я не нашел способа короче.  Подмигивающий

З.Ы.
Смотря, что прятать в классе.  Подмигивающий

З.Ы.
Да, кстати подобные вызовы стоят у меня не где попало, а где это необходимо (например в функции мат. операций, логики и работы со строками, а также при записи переменных в память). ИМХО, класс достаточно инкапсулирован в соответствии с той задачей, для которой он был создан. Подмигивающий
« Последнее редактирование: Март 08, 2011, 16:53 от Eten » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #53 : Март 08, 2011, 17:30 »

Да, кстати подобные вызовы стоят у меня не где попало, а где это необходимо (например в функции мат. операций, логики и работы со строками, а также при записи переменных в память). ИМХО, класс достаточно инкапсулирован в соответствии с той задачей, для которой он был создан. Подмигивающий
Ой, ну вот не надо прятаться за специфику задачи и рассказывать сказки "про белого бычка"  Улыбающийся Вопрос о "типе результата" прекрасно решается на уровне класса, напр.

Код
C++ (Qt)
// friend
NNumeric operator + ( const NNumeric & arg0, const NNumeric & arg1 )
{
bool useReal = arg0.IsReal() || arg1.IsReal();
return NNumeric(arg0.mValue + arg1.mValue, useReal);
}
 
NNumeric::NNumeric( double val, bool useReal )
{
mIsReal = useReal;
CheckLimits(val);
mValue = val;
}
 
Я не помню точно имена членов класса - но не суть

Edit: да и вообще по-хорошему метод IsReal должен быть private
« Последнее редактирование: Март 08, 2011, 17:42 от Igors » Записан
Eten
Гость
« Ответ #54 : Март 08, 2011, 17:40 »

Ладно, убедили.

Но скажу сразу, что не подумал как-то об этом, изначально код то у меня был другой (т.е. явно не было видно). И постоянно что-то переписывая, можно и не заметить, как придешь к такому.  Строит глазки
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #55 : Март 08, 2011, 18:10 »

brankovic, вот так бы сразу и сказали.  Подмигивающий Я, честно говоря, помню о работе с указателями, но что-то восприятие надо мной шутку сыграло.  Строит глазки Да, конструктор действительно оказался уже не нужен (в классе его убрал), а вот и та функция (пока она будет без  дополнительных проверок, это буду писать позднее), о которой вы говорили:

Код:
NNumeric NEngine::PopNumeric()
{
    NDataTypes* dt;
    NNumeric arg;
    dt = this->StackValue.pop();
    arg = *dynamic_cast<NNumeric*>(dt);
    delete dt;
    return arg;
}
А зачем здесь dt удалять?? Или так задумано, что при каждом вызове PopNumeric удалять очередной элемент в StackValue? Это не хорошо..
Короче полный даркнэсс, как говорит один мой знакомый)
Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #56 : Март 08, 2011, 18:36 »

Код:
NNumeric NEngine::PopNumeric()
{
    NDataTypes* dt;
    NNumeric arg;
    dt = this->StackValue.pop();
    arg = *dynamic_cast<NNumeric*>(dt);
    delete dt;
    return arg;
}
А зачем здесь dt удалять?? Или так задумано, что при каждом вызове PopNumeric удалять очередной элемент в StackValue? Это не хорошо..
Короче полный даркнэсс, как говорит один мой знакомый)
Ну почему нехорошо? "pop" предполагает что ответственность за "снятый" элемент возьмет на себя кто-то другой, может и удалить, это нормально. Другое дело вот это порно
Код
C++ (Qt)
   dt = this->StackValue.pop();
 
Зачем же так "серпом по нежному месту"?  Если имя не придумалось, просто доливаете артикль, напр
Код
C++ (Qt)
   dt = theStack.pop();
 
Просто и со вкусом
Записан
m_ax
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2095



Просмотр профиля
« Ответ #57 : Март 08, 2011, 18:47 »

Цитировать
Ну почему нехорошо? "pop" предполагает что ответственность за "снятый" элемент возьмет на себя кто-то другой, может и удалить, это нормально.
В смысле? Возвращает же функция не указатель...
Даже если бы и указатель, то delete dt порушит весь объект к чёрту..
Т.е. попробуйте вызвать эту функцию дважды PopNumeric() интересно, что получится)
« Последнее редактирование: Март 08, 2011, 18:57 от m_ax » Записан

Над водой луна двурога. Сяду выпью за Ван Гога. Хорошо, что кот не пьет, Он и так меня поймет..

Arch Linux Plasma 5
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #58 : Март 08, 2011, 19:27 »

Цитировать
Ну почему нехорошо? "pop" предполагает что ответственность за "снятый" элемент возьмет на себя кто-то другой, может и удалить, это нормально.
В смысле? Возвращает же функция не указатель...
Даже если бы и указатель, то delete dt порушит весь объект к чёрту..
Т.е. попробуйте вызвать эту функцию дважды PopNumeric() интересно, что получится)
Цитировать
- Нет-нет, я не туда попал
- Да как же не туда - да именно сюда
(глупые стихи случайно застрявшие в памяти  Улыбающийся)
"pop" снимает из очереди LIFO (стек) но ничего не обещает об удалении. Последовательный вызов 2 и более pop приведет к снятию 2 и более тех кто был на стеке - это нормально. Конечно Вы это знаете, просто заработались/заскок  Улыбающийся
Записан
brankovic
Гость
« Ответ #59 : Март 08, 2011, 19:44 »

Короче полный даркнэсс, как говорит один мой знакомый)

Просто Eten на тёмной стороне силы. Но это не значит, что он не станет великим программистом Подмигивающий
Записан
Страниц: 1 2 3 [4] 5 6   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.215 секунд. Запросов: 23.