На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> получить указатель на производный класс , из указателя на виртуальный базовый
    имеем что-то вроде:

    class Base{ };

    class BaseA: virtual public Base{ };
    class BaseB: virtual public Base{ };

    class MyClass: public BaseA, public BaseB{ };

    хотелось бы работать со списком указателей на Base
    и когда надо получать из них MyClass

    как такое организовать ?
      MyClass* pObj = dynamic_cast< MyClass* >(VectorBases[ i]);
      или я че не понял...
        Цитата
        AlexSm, 19.01.04, 18:01
        MyClass* pObj = dynamic_cast< MyClass* >(VectorBases[ i]);


        если класс не содержит виртуальных функций то имеем E2307:

        Цитата
        A dynamic_cast was used with a pointer to a class type that is either undefined, or doesn't have any virtual member functions.
          Добавь виртуальный деструктор в Base и забудь про эту ошибку. Вообще виртуальные деструкторы - это есть хорошо.
            конечно же деструктор базового класса виртуальный, просто когда рассматривал совет
            AlexSm забыл virtual приписать. Кастует, все-тип топ. Но немного не то что я бы хотел...
            кто-нибудь в CPU Window смотрел !? во скока строк асма это все превратиться.
            Мне такая роскошь не по карману, дешевле на MyClass * список хранить.

            Думал может кто предложит как-нить быстро и сердито, типа:

            MyClass *mc = new MyClass;
            Base *bc = mc;

            кастуем:
            MyClass *mc_ptr = (MyClass *)( (void *)bc ); //неправильно

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

            Попутно вопрос созрел:
            Никогда раньше dynamic_cast не использовал в каких целях он полезен (бесполезен ;) ) ?
              А dynamic_cast вроде применяется, даже если его и не писать, хотя положено вроде. Или я ошибаюсь?
                Дело в том, что структура класса может быть очень сложной. Это раз. Ты, как разработчик, об этой структуре никаких предположений делать не можешь (особенно в варианте со множественным наследованием) - это два. Таким образом, по любому лучше, если преобразование будет делать сам компилятор на основании RTTI и т. п. информации.
                Пердложенный тобою вариант кастинга:
                Цитата
                Sazabis, 19.01.04, 22:09
                MyClass *mc_ptr = (MyClass *)( (void *)bc )

                является грубейшей ошибкой, т. к. даже ты, как разработчик, не сможешь сказать, что в итоге получится.
                Итог - если не хочешь гемороя и недель отладки использую dynamic_cast, несмотря на то, что это приводит к некоторому количеству строк на асме.


                Цитата
                ADA, 19.01.04, 23:40
                А dynamic_cast вроде применяется, даже если его и не писать, хотя положено вроде. Или я ошибаюсь?

                Ты имеешь в виду C-style cast? Вполне возможно. Но обычно он рассматривается как аналог reinterpret_cast'а.
                  Цитата
                  Flex_Ferrum, 20.01.04, 10:08
                  Итог - если не хочешь гемороя и недель отладки использую dynamic_cast, несмотря на то, что это приводит к некоторому количеству строк на асме.


                  решил занятся оптимизацией кода, готов ко всему ;)

                  Цитата
                  Flex_Ferrum, 20.01.04, 10:08
                  Ты, как разработчик, об этой структуре никаких предположений делать не можешь (особенно в варианте со множественным наследованием)


                  это то как раз проходит на ура.

                  ExpandedWrap disabled
                    MyClass *mc = new MyClass;
                    BaseA *ba_ptr = mc;
                     
                    MyClass *mc_ptr = (MyClass *)ba_ptr;


                  а вот при виртуальном наследовании... я удивлен если честно, посему и интересно.

                  Цитата
                  ADA, 19.01.04, 23:40
                  А dynamic_cast вроде применяется, даже если его и не писать, хотя положено вроде. Или я ошибаюсь?


                  нет, если его не писать то он не вызывается, смотрел по асму.
                    Цитата

                    а вот при виртуальном наследовании... я удивлен если честно, посему и интересно.

                    Что при виртуальном наследовании?
                    Просто я тут набросал, то что ты говоришь...
                    И вот так все работает:
                    ExpandedWrap disabled
                       
                      class Base{
                      public:
                          Base(){}
                          virtual ~Base(){}
                      };
                       
                      class BaseA : public Base{
                      public:
                          BaseA(){}
                          virtual ~BaseA(){}
                      };
                       
                      class BaseB : public Base{
                      public:
                          BaseB(){}
                          virtual ~BaseB(){}
                      };
                       
                      class MyClass :
                          public BaseA,
                          public BaseB{
                      public:
                          MyClass(){}
                          virtual ~MyClass(){}
                      };

                    Ну а далее:
                    ExpandedWrap disabled
                       
                          MyClass *mc = new MyClass;
                          Base *bc = reinterpret_cast<Base *>(mc);
                          MyClass *mc_ptr=reinterpret_cast<MyClass *>(bc);


                    И никаких тебе ошибок!
                    Сообщение отредактировано: ViGOur -
                      Цитата
                      ViGOur, 21.01.04, 19:59
                      Ну а далее:


                      MyClass *mc = new MyClass;
                      Base *bc = reinterpret_cast<Base *>(mc);
                      MyClass *mc_ptr=reinterpret_cast<MyClass *>(bc);



                      И никаких тебе ошибок!


                      никаких, все ведь правильно.
                      только преобразование

                      MyClass *mb_ptr = (MyClass *)bc; // тут я не имею ввиду Base, просто явное преобразование.
                      гораздо быстрее
                      MyClass *mc_ptr=reinterpret_cast<MyClass *>(bc);

                      Гораздо, конечно же в кавычках :) для 500 000 итераций в каждой из которых не менее 10 раз точно используются подобные преобразования, dynamic_cast или reinterpret_cast отстает на пару секунд :( Вот такие дела.
                        Цитата Sazabis @ 22.01.04, 13:38
                        ...
                        ...
                        Base, просто явное преобразование.
                        гораздо быстрее
                        MyClass *mc_ptr=reinterpret_cast<MyClass *>(bc);

                        Гораздо, конечно же в кавычках :) для 500 000 итераций в каждой из которых не менее 10 раз точно используются подобные преобразования, dynamic_cast или reinterpret_cast отстает на пару секунд :( Вот такие дела.

                        Так...Вы тут не путайте понятия! Работать оно конечно будет, а вот по стандарту??? ;)
                        Читаем для начала это: dynamic_cast
                        Затем это: reinterpret_cast
                        Sazabis Улавливаешь всю разницу между ними??? И вопрос об отставании на пару секунд...явно лишний :)
                          Улавливаешь :) при чем все лучше ;)

                          только в чем проблема тут:

                          class A{ };

                          class B: public A{ };


                          B *b = new B;
                          A *pa = b;
                          B *pb = ( B *)pa; // <- тут
                          неужто надо писать

                          B *pb = dynamic_cast< B *>( pa ); ?

                          ?
                            Цитата
                            Sazabis, 22.01.04, 14:51
                            B *pb = ( B *)pa; // <- тут
                            неужто надо писать

                            B *pb = dynamic_cast< B *>( pa ); ?

                            Да. Надо именно dynamic_cast.
                              Цитата
                              Flex_Ferrum, 22.01.04, 15:03
                              Да. Надо именно dynamic_cast.


                              так ведь работает !?
                                Цитата
                                Sazabis, 22.01.04, 15:18
                                так ведь работает !?

                                Угумс. А вот так:
                                ExpandedWrap disabled
                                   
                                  class A {;}
                                  class B : public A {;}
                                  class C : public A {;}
                                   
                                   
                                  B b;
                                  A* pa = &b;
                                  C* pc = (C*)a;

                                ?
                                  аналогично этому

                                  ExpandedWrap disabled
                                    C* pc = dynamic_cast< C *>( pa );


                                  и вооПче это же логическая ошибка !?
                                    Цитата
                                    Sazabis, 22.01.04, 16:00
                                    аналогично этому
                                    C* pc = dynamic_cast< C *>( pa );
                                    и вооПче это же логическая ошибка !?

                                    Нет, не аналогично. По той простой причине, что dynamic_cast в этом случае тебе вернет NULL (если кастишь указатели), или выбросит исключение bad_cast, если кастишь ссылки.
                                    На счет логической ошибки. В приведенном примере - да. А предположим, что ты передаешь pa в метод, где это pa кастится до одного из потомков? Там такая ошибка не столь очевидна.
                                      ну теперь, вообще, почти все :) понятно B)

                                      А если взять отдельный класс, внутри его методов я как его разработчик, обязуюсь отследить все неровности и шероховатости. Не использование dynamic_cast внутри этих методов позволит мне кое в чем выграть. Есть ли в этом грубая ошибка ?
                                        Цитата
                                        Sazabis, 22.01.04, 16:45
                                        А если взять отдельный класс, внутри его методов я как его разработчик, обязуюсь отследить все неровности и шероховатости. Не использование dynamic_cast внутри этих методов позволит мне кое в чем выграть. Есть ли в этом грубая ошибка ?

                                        Скорее, некрасивость. И в этом случае, если и кастить - то через C-style cast, и ни вкоем случае не использовать reinterpret_cast. В ряде случаев можно static_cast, но только для случаев downcast'а.
                                          Цитата
                                          Flex_Ferrum, 22.01.04, 16:49
                                          Скорее, некрасивость


                                          да, в коде не очень красиво :(

                                          Цитата
                                          Flex_Ferrum, 22.01.04, 16:49
                                          И в этом случае, если и кастить - то через C-style cast


                                          через него

                                          Цитата
                                          Flex_Ferrum, 22.01.04, 16:49
                                          ни вкоем случае не использовать reinterpret_cast.


                                          не, конечно, обойдусь ;)

                                          Цитата
                                          Flex_Ferrum, 22.01.04, 16:49
                                          В ряде случаев можно static_cast, но только для случаев downcast'а


                                          а это еще зачем ? тут то какие проблемы ?
                                            Цитата
                                            Sazabis, 22.01.04, 17:10
                                            Цитата
                                            Flex_Ferrum, 22.01.04, 16:49
                                            В ряде случаев можно static_cast, но только для случаев downcast'а


                                            а это еще зачем ? тут то какие проблемы ?

                                            Дополнительный контроль на этапе компиляции.
                                              Цитата
                                              Sazabis, 22.01.04, 13:45
                                              Не использование dynamic_cast внутри этих методов позволит мне кое в чем выграть.



                                              Не стоит с этим заморачиваться. Богатая практика различных людей доказала - оптимизировать нужно алгоритмы, а не микромоменты. Прибавка производительности таким путем оптимизации чаще всего несущественна по сравнению с трудозатратами на нее и проблемами, которая она создает. Хотя, конечно, как развлечение это в каком-то смысле интересно, но в реальных продуктах акценты обычно другие.
                                                Цитата
                                                Fantasist, 23.01.04, 01:08
                                                Хотя, конечно, как развлечение это в каком-то смысле интересно,


                                                Добавлено в :
                                                Вобщем, все понятно стало. Всем спасибо за внимание, особо AlexSm, и особо-особо :) Flex_Ferrum, в частности за 17 пост B)

                                                Награждаю оных плюсиками :) считаю тему закрытой
                                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                0 пользователей:


                                                Рейтинг@Mail.ru
                                                [ Script execution time: 0,0462 ]   [ 16 queries used ]   [ Generated: 27.04.24, 08:04 GMT ]