Форум программистов, компьютерный форум CyberForum.ru

Не могу разобраться с dynamic_cast - C++

Восстановить пароль Регистрация
 
stzer
38 / 59 / 17
Регистрация: 26.10.2013
Сообщений: 172
Завершенные тесты: 2
26.07.2014, 13:41     Не могу разобраться с dynamic_cast #1
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Base
{
public:
    virtual void info()
    {
        cout<<"Base"<<endl;
    }
};
 
class Derived : public Base
{
public:
    void info()
    {
        cout<<"Derived"<<endl;
    }
};
 
void main()
{
    Base *bp, base;
    Derived *dp, derived;
    bp=&base;
    bp->info();//Выведет Base
    dynamic_cast<Derived*>(bp);
    bp->info(); //Выведет Base, а мне нужно Derived
    system("pause");
}
Никак не могу разобраться с этим оператором.
Книги и статьи в интернете не помогли, помогите пожалуйста.
Лучшие ответы (1)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
26.07.2014, 13:59     Не могу разобраться с dynamic_cast #2
Цитата Сообщение от stzer Посмотреть сообщение
dynamic_cast<Derived*>(bp);
Во-первых, результат dynamic_cast нужно чему-то присвоить. Он не изменяет свой аргумент.
Во-вторых, он не поможет тебе сделать то, чего ты хочешь

Добавлено через 6 минут
Вот.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Base
{
public:
    virtual void info()
    {
        cout<<"Base"<<endl;
    }
};
 
class Derived : public Base
{
public:
    void info()
    {
        cout<<"Derived"<<endl;
    }
};
 
int main()
{
    Base *bp, base;
    Derived *dp, derived;
    bp=&base;
    bp->info();//Выведет Base
    bp=&derived;
    bp->info(); //Выведет Derived
    system("pause");
}
Ну или объясни подробнее чего хочешь добиться.
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
26.07.2014, 13:59     Не могу разобраться с dynamic_cast #3
Цитата Сообщение от DrOffset Посмотреть сообщение
Во-первых, результат dynamic_cast нужно чему-то присвоить.
Не обязательно, особенно если тип ссылочный.
stzer, чтобы получить вывод характерный для производного класса указатель должен указывать на объект этого (производного) класса.
Т.е. в первом приближении достаточно добавить:
C++
1
bp=&derived;
stzer
38 / 59 / 17
Регистрация: 26.10.2013
Сообщений: 172
Завершенные тесты: 2
26.07.2014, 14:00  [ТС]     Не могу разобраться с dynamic_cast #4
DrOffset, Ладно, хорошо.
dynamic_cast используется для проверки типов объектов
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <typeinfo>
 
class Base
{
    virtual void vertFunc()
    { }
};
class Derv1 : public Base
{ };
class Derv2 : public Base
{ };
bool isDerv1(Base *pUnknown)
{
    Derv1 *pDerv1;
    if(pDerv1=dynamic_cast<Derv1*>(pUnknown))
        return true;
    else return false;
}
int main()
{
    Derv1 *d1=new Derv1;
    Derv2 *d2=new Derv2;
    
    if(isDerv1(d1))
        cout<<"d1 - object from class Derv1"<<endl;
    else
        cout<<"d1 - not object class Derv1"<<endl;
    if(isDerv1(d2))
        cout<<"d2 - object from class Derv1"<<endl;
    else
        cout<<"d2 - not object class Derv1"<<endl;
 
    system("pause");
    return 0;
}
Тут более менее все понятно.
Тогда вот, цитата:
"Операция в основном применятся для преобразования указателей родственных классов иерархии, в основном - указателя базового класса в указатель на производный..."
В главе "Изменение типов указателей с помощью dynamic_cast" (Лафоре) есть такое пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class Base
{
protected: 
    int ba;
public:
    Base() : ba(0)
    { }
    Base(int b) : ba(b)
    { }
    virtual void vertFunc()
    { }
    void show()
    { cout<<"Base: ba = "<<ba<<endl; }
};
class Derv : public Base
{ 
private:
    int da;
public:
    Derv(int b,int d) : Base(b), da(d)
    { }
    void show()
    { cout<<"Derv: ba = "<<ba<<" da = "<<da<<endl; }
};
 
int main()
{
    Base *pBase=new Base(10);
    Derv *pDerv=new Derv(21,22);
    pBase=dynamic_cast<Base*>(pDerv);
    pBase->show();
    pBase=new Derv(31,32);
    pDerv=dynamic_cast<Derv*>(pBase);
    pDerv->show();
    system("pause");
    return 0;
}
Зачем он тут вообще использует dynamic_cast? Я уже голову сломал.
DrOffset
26.07.2014, 14:03
  #5

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
Не обязательно, особенно если тип ссылочный.
Я вообще-то говорил только про данный случай. Придираться тоже надо уметь

Tulosba
26.07.2014, 14:09
  #6

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Придираться тоже надо уметь
Вот это имелось в виду:
C++
1
dynamic_cast<Derived*>(bp)->info()

DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
26.07.2014, 14:12     Не могу разобраться с dynamic_cast #7
Цитата Сообщение от stzer Посмотреть сообщение
Зачем он тут вообще использует dynamic_cast? Я уже голову сломал.
Обрати внимание, что у него функция show невиртуальная.

Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от Tulosba Посмотреть сообщение
dynamic_cast<Derived*>(bp)->info()
Да, я понял. Теперь ты пойми, я здесь не объяснял общие правила, а лишь сделал замечение по поводу того, что выражение с dynamic_cast у автора ни на что не влияет т.к. он не использует результат. Т.е. он полагал, что dynamic_cast изменяет свой аргумент.

stzer
38 / 59 / 17
Регистрация: 26.10.2013
Сообщений: 172
Завершенные тесты: 2
26.07.2014, 14:13  [ТС]     Не могу разобраться с dynamic_cast #8
DrOffset, Хм,
А что происходит вот здесь
C++
1
pBase=dynamic_cast<Base*>(pDerv);
Объясни пожалуйста подробнейшим образом.
Просто если я в последнем листинге закомментирую строки с dynamic_cast это не повлияет на результат.
DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
26.07.2014, 14:25     Не могу разобраться с dynamic_cast #9
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от stzer Посмотреть сообщение
А что происходит вот здесь
Приводит указатель на объект наследника к указателю на объект базовго класса, используя динамическую информацию о типах.
Вообще-то такое преобразование выполняется автоматическим и не требует dynamic_cast, т.к. класс наследника всегда знает своих родителей. В данном случае эффект будет эквивалентен вот этому:
C++
1
pBase = pDerv;
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
26.07.2014, 14:27     Не могу разобраться с dynamic_cast #10
Глупость происходит. Вполне можно было написать
C++
1
pBase = pDerv;
dynamic_cast нужен для нисходящего, относительно иерархии наследования, приведения типов
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
26.07.2014, 14:29     Не могу разобраться с dynamic_cast #11
C++
1
pBase=dynamic_cast<Base*>(pDerv);
Преобразование указателя на производный класс в указатель на базовый класс происходит неявно. Никакие касты тут не нужны. Можно просто:
C++
1
pBase = pDerv;
Но, видимо, для единообразия написали с dynamic_cast.
stzer
38 / 59 / 17
Регистрация: 26.10.2013
Сообщений: 172
Завершенные тесты: 2
26.07.2014, 14:29  [ТС]     Не могу разобраться с dynamic_cast #12
DrOffset, Спасибо, походу что-то прояснилось.
DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
26.07.2014, 14:36     Не могу разобраться с dynamic_cast #13
Цитата Сообщение от stzer Посмотреть сообщение
Просто если я в последнем листинге закомментирую строки с dynamic_cast это не повлияет на результат.
Потому что это код в main так составлен, возможно не очень наглядно. Посмотри, там изначально все указатели указывают на ожидаемые экземпляры, соответсвенно вывод не меняется. К тому же там ошибка, которая приводит к утечке памяти: pBase затирается (в первом dynamic_cast) другим значением и мы "теряем" указатель.

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

Добавлено через 3 минуты
stzer, Вообще, вот из-за таких вот примеров поголовно все, кто по ним учился, начинают ассоциировать полиморфизм с new, что в общем-то неправильно.
stzer
38 / 59 / 17
Регистрация: 26.10.2013
Сообщений: 172
Завершенные тесты: 2
26.07.2014, 14:36  [ТС]     Не могу разобраться с dynamic_cast #14
DrOffset, и еще тогда попутно
При использовании этого dynamic_cast<Derived*>(bp)->info()
вылетает ошибка. Как его использовать?

А по каким примерам учиться тогда?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.07.2014, 22:18     Не могу разобраться с dynamic_cast
Еще ссылки по теме:

Не могу разобраться C++
не могу разобраться C++
C++ Не могу разобраться

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
DrOffset
6457 / 3831 / 885
Регистрация: 30.01.2014
Сообщений: 6,627
26.07.2014, 22:18     Не могу разобраться с dynamic_cast #15
Цитата Сообщение от stzer Посмотреть сообщение
Как его использовать?
Значит в bp на самом деле не Derived. Возвращается ноль и вызов info приводит к ошибке. Надо проверять результат перед вызовом или использовать ссылочный вариант dynamic_cast<Derived&>(*bp), он генерирует исключение (std::bad_cast) при неправильном касте. Но исключение все равно надо где-то обрабатывать.

Добавлено через 7 часов 39 минут
Цитата Сообщение от stzer Посмотреть сообщение
А по каким примерам учиться тогда?
К сожалению нет таких книг, в которых бы совсем не было ошибок. Так что в сложившейся ситуации нужно просто проверять несколько источников, скажем одновременно несколько книг. Так хотя бы немного повысится вероятность, что информация не будет однобокой.
Yandex
Объявления
26.07.2014, 22:18     Не могу разобраться с dynamic_cast
Ответ Создать тему
Опции темы

Текущее время: 23:35. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru