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

dynamic_cast - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 13, средняя оценка - 4.85
Eugine
 Аватар для Eugine
3 / 3 / 0
Регистрация: 10.11.2012
Сообщений: 63
25.10.2013, 15:08     dynamic_cast #1
Помогите разобраться с dynamic_cast, а точнее с вот этой записью
C++ (Qt)
1
2
3
4
5
6
7
8
9
void f() {
   A* pa = new A;
   B* pb = new B;
   void* pv = dynamic_cast<void*>(pa);
   // pv now points to an object of type A
 
   pv = dynamic_cast<void*>(pb);
   // pv now points to an object of type B
}
Тоесть, если я сделаю вот так
C++ (Qt)
1
2
3
Derived* pd = new Derived;
Base* pb = dynamic_cast<Base*>(pa);
void* pbd = dynamic_cast<void*>(pb);
то pbd будет указывать на Derived? И если так, то как можно после этого использовать методы этого класса?

Или здесь смысл именно в том, чтобы передать в void* адрес класса? Тогда почему не использовать бы какой-нибудь другой каст?

P.S: dynamic_cast можно применять только от Derived к Base?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.10.2013, 15:08     dynamic_cast
Посмотрите здесь:

dynamic_cast C++
dynamic_cast C++
dynamic_cast() шаблон C++
C++ Объясните dynamic_cast
C++ Ошибка dynamic_cast: __non_rtti_object
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
25.10.2013, 15:11     dynamic_cast #2
Цитата Сообщение от Eugine Посмотреть сообщение
Тогда почему не использовать бы какой-нибудь другой каст?
это у тебя надо спросить. почему не использовать бы какой-нибудь другой каст?

Добавлено через 1 минуту
Цитата Сообщение от Eugine Посмотреть сообщение
C++
1
Base* pb = dynamic_cast<Base*>(pa);
Цитата Сообщение от Eugine Посмотреть сообщение
то pbd будет указывать на Derived?
а кто такой pa ?
Eugine
 Аватар для Eugine
3 / 3 / 0
Регистрация: 10.11.2012
Сообщений: 63
25.10.2013, 15:14  [ТС]     dynamic_cast #3
Я просто разбираюсь с dynamic_cast, он позволяет работать с классами и void*. И вот возник вопрос, чем void* так выделился.

Добавлено через 1 минуту
Цитата Сообщение от Jupiter Посмотреть сообщение
это у тебя надо спросить. почему не использовать бы какой-нибудь другой каст?

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


а кто такой pa ?
извиняюсь, там не pa, а pd

C++ (Qt)
1
2
3
Derived* pd = new Derived;
Base* pb = dynamic_cast<Base*>(pd);
void* pbd = dynamic_cast<void*>(pb);
Jupiter
Каратель
Эксперт C++
6543 / 3963 / 226
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
Завершенные тесты: 2
25.10.2013, 15:15     dynamic_cast #4
Цитата Сообщение от Eugine Посмотреть сообщение
Я просто разбираюсь с dynamic_cast, он позволяет работать с классами и void*
чорд, а я и не знал блин (интересно, где такое пишут? в топку этот источник), а ты знаешь что ножем можно резать хлеб, а можно и пальцы отрезать?

почитай хотя бы в вики про dynamic_cast
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 15:25     dynamic_cast #5
Тут неплохо описаны разные приведения типов на основе ***_cast

Не по теме:

Кстати, я недавно ввёл в язык С++ еще один метод приведения типа: cast_away<type>(variable) - это один из самых нахальных и безжалостных методов приведения типов. Будет введен в стандарт языка С++18

ct0r
C++/Haskell
 Аватар для ct0r
1550 / 569 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
25.10.2013, 16:47     dynamic_cast #6
Цитата Сообщение от Eugine Посмотреть сообщение
то pbd будет указывать на Derived? И если так, то как можно после этого использовать методы этого класса?
Цитата Сообщение от Jupiter Посмотреть сообщение
чорд, а я и не знал блин (интересно, где такое пишут? в топку этот источник), а ты знаешь что ножем можно резать хлеб, а можно и пальцы отрезать?
К void* иногда нужно приводить. При множественном наследовании это позволяет получить указатель на самое начало объекта.
oxotnik
25.10.2013, 16:51
  #7

Не по теме:

не знал, что можно кастить к воиду*

Shtirliz72
200 / 160 / 38
Регистрация: 25.10.2013
Сообщений: 527
25.10.2013, 16:52     dynamic_cast #8
Почему при приведении к <void *> не использовать static_cast?
Это намного быстрее.
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 16:54     dynamic_cast #9
Цитата Сообщение от Shtirliz72 Посмотреть сообщение
Почему при приведении к <void *> не использовать reinterpret_cast?
Это намного быстрее.
Быстрее чем что?
ct0r
C++/Haskell
 Аватар для ct0r
1550 / 569 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
25.10.2013, 16:55     dynamic_cast #10
Цитата Сообщение от Shtirliz72 Посмотреть сообщение
Почему при приведении к <void *> не использовать reinterpret_cast?
Это намного быстрее.
Потому что при множественном наследовании полученный указатель не будет указывать на начало объекта.
Shtirliz72
200 / 160 / 38
Регистрация: 25.10.2013
Сообщений: 527
25.10.2013, 16:59     dynamic_cast #11
Цитата Сообщение от castaway Посмотреть сообщение
Быстрее чем что?
Не, это я неверно написал, уже исправил. reinterpret_cast нельзя использовать с void* .

Цитата Сообщение от ct0r Посмотреть сообщение
Потому что при множественном наследовании полученный указатель не будет указывать на начало объекта.
Ясно. static_cast это тоже касается?
ct0r
C++/Haskell
 Аватар для ct0r
1550 / 569 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
25.10.2013, 17:05     dynamic_cast #12
Цитата Сообщение от Shtirliz72 Посмотреть сообщение
Ясно. static_cast это тоже касается?
Да. Ни один каст кроме dynamic_cast не использует RTTI.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
using namespace std;
 
struct A { int a; virtual ~A(){} };
struct B { int b; virtual ~B(){} };
struct C: A, B { int c; };
 
void foo(B* obj)
{
    cout << static_cast<void*>(obj) << endl;
    cout << dynamic_cast<void*>(obj);
}
 
int main() {
    C* c = new C;
    cout << c << endl;
    foo(c);
    return 0;
}
0x9166008
0x9166010
0x9166008
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 17:08     dynamic_cast #13
А в чем смысл преобразования к типу void * в данном случае?

Добавлено через 3 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
using namespace std;
 
struct A { int a; virtual ~A(){} };
struct B { int b; virtual ~B(){} };
struct C: A, B { int c; };
 
int main()
{
    C* c = new C;
    cout << c << endl;
    cout << (void *)c << endl;
    cout << static_cast<void*>(c) << endl;
    cout << dynamic_cast<void*>(c) << endl;
    cout << reinterpret_cast<void*>(c) << endl;
 
    return 0;
}
0x9e2e58
0x9e2e58
0x9e2e58
0x9e2e58
0x9e2e58
ct0r
C++/Haskell
 Аватар для ct0r
1550 / 569 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
25.10.2013, 17:14     dynamic_cast #14
Цитата Сообщение от castaway Посмотреть сообщение
А в чем смысл преобразования к типу void * в данном случае?
Ты имеешь в виду зачем нам нужно получать указатель на начало объекта или что?

Ну в твоем коде очевидно, что адреса будут одинаковые. Потому что нет преобразований, которые бы сдвигали указатель (у меня это из C* в B*).
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 17:23     dynamic_cast #15
ct0r, в 12-м посте у меня такой же вывод как и у тебя.. видимо я чего-то недопонимаю.. Чего именно? Почему в функции объект имеет другое "основание" ?

Почему следующий вариант выдает одинаковые значения:
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
#include <iostream>
 
using namespace std;
 
struct A { int a; virtual ~A(){} };
struct B { int b; virtual ~B(){} };
struct C: A, B { int c; };
 
void test( C * c ) {
    cout << c << endl;
    cout << (void *)c << endl;
    cout << static_cast<void*>(c) << endl;
    cout << dynamic_cast<void*>(c) << endl;
    cout << reinterpret_cast<void*>(c) << endl;
}
 
int main()
{
    C* c = new C;
    test( c );
 
    cout << c << endl;
    cout << (void *)c << endl;
    cout << static_cast<void*>(c) << endl;
    cout << dynamic_cast<void*>(c) << endl;
    cout << reinterpret_cast<void*>(c) << endl;
 
    return 0;
}
?

0x502e58
0x502e58
0x502e58
0x502e58
0x502e58
0x502e58
0x502e58
0x502e58
0x502e58
0x502e58
Добавлено через 4 минуты
Тьфу, блин.. у тебя ж там другой объект..
ct0r
C++/Haskell
 Аватар для ct0r
1550 / 569 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
25.10.2013, 17:25     dynamic_cast #16
C* c = new C; - тут c указывает на объект самого производного класса
При вызове функции идет преобразование из C* в B*, после которого с указывает уже на подобъект класса В, который неявно содержится в классе С.
Только dynamic_cast пользуется информацией о полиморфных типах, поэтому только он потом может восстановить указатель на самый производный класс.
Это полезная фича, когда нам нужно уметь отличать подобъекты одного объекта от других подобъектов. Или при сериализации.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
25.10.2013, 17:27     dynamic_cast
Еще ссылки по теме:

C++ dynamic_cast
Dynamic_cast и полиморфизм C++
C++ Работа с dynamic_cast

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

Или воспользуйтесь поиском по форуму:
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
25.10.2013, 17:27     dynamic_cast #17
Я понял что ты хотел сказать. dynamic_cast приводит тип к указателю производного.
Yandex
Объявления
25.10.2013, 17:27     dynamic_cast
Ответ Создать тему
Опции темы

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