Название: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 06, 2012, 19:33 Звачем нужны dynamic_cast, static_cast, reinterpret_cast, qobject_cast и т д?
Сколько статей читал, толком суть не понял чот(( Ведь вроде можно проще приводить к типам. например Код
а между float и double вообще неявное приведение, то есть можно прям вот так: Код
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 06, 2012, 19:57 Ну вообще-то форум - не для изучения основ, та что придется отправлять на гугл :) Просто наберите напр static_cast C++ попадете на Алену, девушка доходчиво пишет. Обижаться на форумчан не надо, никому не охота переписывать гугл - а ответ на этот вопрос может быть только таким.
По поводу простых типов. Если 2 типа совместимы по присваиванию, то один из них всегда "старше" а др "младше". Если младший присваивается старшему, никакие приведения не нужны. Примеры Код
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Blackwanderer от Марта 06, 2012, 19:59 dynamic_cast - приведение указателей на классы из одной иерархии (указатель на родителя к указателю на потомка и наоборот); проверка на корректность приведение выполняется всегда (в процессе выполнения программы), некорректное приведение не выполняется
static_cast - приведение любых типов (для базовых типов аналогичен привидению в стиле C, для классов и указателей более строго проверяет корректность приведения); проверка на корректность выполняется всегда (на этапе компиляции), некорректное приведение не выполняется только в наиболее очевидных случаях reinterpret_cast - приведение любых типов; проверка на корректность не выполняется. Привидение в стиле C, вначале пробует static_cast, затем, если не получилось, reinterpret_cast, т.е. приведение в стиле C потенциально более опасно. Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Blackwanderer от Марта 06, 2012, 20:04 Ну вообще-то форум - не для изучения основ Не согласен, что это - основы. Это, скорее, уже тонкости языка.Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 06, 2012, 20:15 dynamic_cast - приведение указателей на классы из одной иерархии (указатель на родителя к указателю на потомка и наоборот); проверка на корректность приведение выполняется всегда (в процессе выполнения программы), некорректное приведение не выполняется Ну если уж вдаваться в тонкости, то dynamic_cast может приводить и не только родителя к потомкуКод
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: kambala от Марта 06, 2012, 23:42 еще забыли про const_cast - снимает модификатор const с переменной
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 07, 2012, 09:33 еще забыли про const_cast - снимает модификатор const с переменной не забыл, просто с const_cast всё ясно и понятно, а вот с остальными не так уж. Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 07, 2012, 09:37 Ну вообще-то форум - не для изучения основ, та что придется отправлять на гугл :) Просто наберите напр static_cast C++ попадете на Алену, девушка доходчиво пишет. Обижаться на форумчан не надо, никому не охота переписывать гугл - а ответ на этот вопрос может быть только таким. По поводу простых типов. Если 2 типа совместимы по присваиванию, то один из них всегда "старше" а др "младше". Если младший присваивается старшему, никакие приведения не нужны. Примеры Код
То есть эти все ..._cast для того чтобы совершать преобразование типов между без потери данных, я так понимаю, верно? Кстати, а если попоробовать преобразовать не связанные никак типы, то есть: Код
Название: Re: Объясните понятно, доступно и просто как д Отправлено: Пантер от Марта 07, 2012, 09:37 Сишное приведение лучше не юзать, ибо его намного тяжелее потом поиском по исходникам найти, чем всякие касты. И оно не безопасно.
Название: Re: Объясните понятно, доступно и просто как д Отправлено: lolbla2 от Марта 07, 2012, 09:41 Сишное приведение лучше не юзать, ибо его намного тяжелее потом поиском по исходникам найти, чем всякие касты. И оно не безопасно. аа так это получается все эти .._cast это С++ стиль приведения типов, а тот стиль Сшный ? Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 07, 2012, 09:51 dynamic_cast - приведение указателей на классы из одной иерархии (указатель на родителя к указателю на потомка и наоборот); проверка на корректность приведение выполняется всегда (в процессе выполнения программы), некорректное приведение не выполняется static_cast - приведение любых типов (для базовых типов аналогичен привидению в стиле C, для классов и указателей более строго проверяет корректность приведения); проверка на корректность выполняется всегда (на этапе компиляции), некорректное приведение не выполняется только в наиболее очевидных случаях reinterpret_cast - приведение любых типов; проверка на корректность не выполняется. Привидение в стиле C, вначале пробует static_cast, затем, если не получилось, reinterpret_cast, т.е. приведение в стиле C потенциально более опасно. спасибо, вполне понятно объяснил и без лишних слов)) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 07, 2012, 15:19 То есть эти все ..._cast для того чтобы совершать преобразование типов между без потери данных, я так понимаю, верно? Потеря данных может быть неизбежной, просто _cast показывает это четко, рельефно Кстати, а если попоробовать преобразовать не связанные никак типы, то есть: До этого дело не дойдет, компилятор не пропустит. А вот приведение (B *) в С стиле пройдет - и потом найти концы может быть непростоКод
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 12:31 Хотелось бы понять ещё некоторые тонкости:
Код
а наоборот если, то тогда что? Код
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Пантер от Марта 11, 2012, 12:42 vB.e будет 3.
vB.h не определено. Наоборот, h потеряется, произойдет "срезка". e останется 1. Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 11, 2012, 12:43 Код
Код
А книжки все-таки надо читать (ну иногда :)) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 13:02 dynamic_cast - приведение указателей на классы из одной иерархии (указатель на родителя к указателю на потомка и наоборот); проверка на корректность приведение выполняется всегда (в процессе выполнения программы), некорректное приведение не выполняется Ну если уж вдаваться в тонкости, то dynamic_cast может приводить и не только родителя к потомкуКод
Кажется ты меня чуток обманул, родителя к потому нельзя приводить, только наоборот потомка можно к родителю привести. Щас попробовал, при приведении таком: Код
Но при таком преобразовании: Код
Что говорит о том, что нельзя папу преобразовать к сыну ;D Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 11, 2012, 13:22 ... Он ведь dynamic :)Что говорит о том, что нельзя папу преобразовать к сыну ;D Код
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 13:28 ... Он ведь dynamic :)Что говорит о том, что нельзя папу преобразовать к сыну ;D Код
ммм.... как здорово, оказывается надо знать такие чёткие тонкости. Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть Код
P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: mutineer от Марта 11, 2012, 13:32 ммм.... как здорово, оказывается надо знать такие чёткие тонкости. Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть Код
P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?) не будет там никакого мусора - при new B() конструктор класса B инициализировал (если в нем прописана эта инициализация, конечно) все поля объекта класса В Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: qt_user от Марта 11, 2012, 13:43 ммм.... как здорово, оказывается надо знать такие чёткие тонкости. Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть Код
P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?) vA это всего лишь указатель на объект класса В и не больше, тонкость состоит только в том что класс А ничего не знает о "новых" полях класса В и указатель на класс А собственно тоже в таком случае чтобы получить доступ к полю h надо сделать приведение: Код: vA = new B(); p.s: доходчиво написано у Шилдта и конечно же документация: http://www.cplusplus.com/doc/tutorial/typecasting/ там все разжевано Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 11, 2012, 13:44 Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть Знову за рибу грошi :'( dynamic_cast делает из одного указателя другой, который может совпадать с исходным или нет. Содержимое/размеры объектов он никак не трогает, они остаются как были созданы. "Мусор" (и обращение к полям которых нет) - это проблема приведения в стиле С, dynamic_cast как раз и был придуман чтобы этого избежать.Код
P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?) Здесь много людей гораздо более начитанных чем я, у них и спрашивайтеНазвание: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 13:47 Цитировать P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?) Здесь много людей гораздо более начитанных чем я, у них и спрашивайтеНу просто спрашиваю у тех, кто в теме отвечает. Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Пантер от Марта 11, 2012, 13:49 lolbla2, почитай Александреску, Саттера и Майерса.
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 13:54 lolbla2, почитай Александреску, Саттера и Майерса. а то я тут за Страуструпа взялся, про приведение типов чот там недостаточно подробно Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: mutineer от Марта 11, 2012, 13:54 lolbla2, почитай Александреску, Саттера и Майерса. а то я тут за Страуструпа взялся, про приведение типов чот там недостаточно подробно Страуструп лишним тоже не будет Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Пантер от Марта 11, 2012, 13:55 Страуструп будет сложноват, лучше начинать с чего-нибудь по-проще.
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 13:59 Страуструп будет сложноват, лучше начинать с чего-нибудь по-проще. Да норм, я же не совсем уж новичёк... 3-4 года программирую, но не особо активно конечно Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 14:27 чуток изменил иерархию классов
Код
как теперь привести от B к С? Код
Название: Re: Объясните понятно, доступно и просто как д Отправлено: mutineer от Марта 11, 2012, 14:32 B к C привести динамиком не получится - это разные классы, и они не наследуются один от другого
Динамик кастует либо вверх по иерархии, либо вниз. А это, грубо говоря, вбок)) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 14:33 B к C привести динамиком не получится - это разные классы, и они не наследуются один от другого Я предполагаю, что надо сначала назад от B к А, а потом от А к С верно? Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: mutineer от Марта 11, 2012, 14:38 B к C привести динамиком не получится - это разные классы, и они не наследуются один от другого Я предполагаю, что надо сначала назад от B к А, а потом от А к С верно? и все равно будет хрень - у тебя объект класса В. Значит легально указывать на него могут указатели типа A* и B*. C* не может легально указывать на объект класса В Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Пантер от Марта 11, 2012, 14:42 Вообще, не стоит юзать касты. Нужно грамотно писать базовые классы.
Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 14:43 B к C привести динамиком не получится - это разные классы, и они не наследуются один от другого Я предполагаю, что надо сначала назад от B к А, а потом от А к С верно? и все равно будет хрень - у тебя объект класса В. Значит легально указывать на него могут указатели типа A* и B*. C* не может легально указывать на объект класса В Ясно, значит нельзя... а вот при такой иерархии: Код
можно от С к А? от А к С? Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: lolbla2 от Марта 11, 2012, 14:44 Вообще, не стоит юзать касты. Нужно грамотно писать базовые классы. Ну это просто мне интересны возможности этих кастов :) Понятно, что в редких случаях это может мне понадобится на практике... Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: LisandreL от Марта 11, 2012, 14:45 как теперь привести от B к С? Никак, они неприводимы и dynamic_cast совершенно правильно возвращает вам нулевой указатель, так как vB не является указателем на С или его наследник.Вы можете, конечно, вызвать C* vC = reinterpret_cast<C*> (vB); и получить указатель, но дальше вам уже никто ничего не гарантирует. Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: mutineer от Марта 11, 2012, 14:47 а вот при такой иерархии: Код
можно от С к А? от А к С? мы же говорим про dynamic_cast, верно? C->A можно кастовать всегда, для этого даже необязательно использовать каст, приведение выполнится неявно. A->C можно кастовать только если объект по указателю является объектом класса С. Если же там объект классов А или В, то каст вернет 0 Общее правило таково - сужать тип можно всегда, а вот расширять только при соблюдении условий Название: Re: Объясните понятно, доступно и просто как д Отправлено: mutineer от Марта 11, 2012, 14:48 Вы можете, конечно, вызвать C* vC = reinterpret_cast<C*> (vB); и получить указатель, но дальше вам уже никто ничего не гарантирует. Новичкам давать такие советы опасно - они обычно не видят фразу "но дальше вам уже никто ничего не гарантирует." :) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: SASA от Марта 11, 2012, 15:09 P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?) http://www.cwer.ru/node/253438/ Купил ещё на первом курсе. Все базовые вещи рассказаны просто и понятно. Название: Re: Объясните понятно, доступно и просто как д Отправлено: lolbla2 от Марта 11, 2012, 15:26 Вы можете, конечно, вызвать C* vC = reinterpret_cast<C*> (vB); и получить указатель, но дальше вам уже никто ничего не гарантирует. Новичкам давать такие советы опасно - они обычно не видят фразу "но дальше вам уже никто ничего не гарантирует." :) Ну я ненастолько новичёк, шишек уже себе понабивал... Читал где-то что reinterpret лучше вообще не использовать, ибо он небезопасен. Насчёт условий когда приводим от родителя к потомку, то есть расширяем, то вроде родительский класс должен быть полиморфным. Название: Re: Объясните понятно, доступно и просто как д Отправлено: mutineer от Марта 11, 2012, 15:33 Насчёт условий когда приводим от родителя к потомку, то есть расширяем, то вроде родительский класс должен быть полиморфным. когда приводим указатель от родителя к потомку, то объект по указателю должен быть этим самым потомком. Ну или потомком потомка:) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 11, 2012, 15:49 как теперь привести от B к С? Никак, они неприводимы и dynamic_cast совершенно правильно возвращает вам нулевой указатель, так как vB не является указателем на С или его наследник.Код Что у Вас печатает? Название: Re: Объясните понятно, доступно и просто как д Отправлено: mutineer от Марта 11, 2012, 15:51 Что у Вас печатает? Мы тут говорим про кастование через dynamic_cast, а ты читеришь используя C-style cast Код
При этом testB указывает на С, но пользоваться таким указателем очень чревато Название: Re: Объясните понятно, доступно и просто как д Отправлено: Igors от Марта 11, 2012, 16:05 Мы тут говорим про кастование через dynamic_cast, а ты читеришь используя C-style cast Я тоже о нем говорюКод Если testB (каким-то образом) был создан как С - dynamic_cast вернет корректный указатель на С. А откуда взялся такой testB - другой вопрос. Др. словами - работает и "вбок" Название: Re: Объясните понятно, доступно и просто как д Отправлено: mutineer от Марта 11, 2012, 16:15 Мы тут говорим про кастование через dynamic_cast, а ты читеришь используя C-style cast Я тоже о нем говорюКод Если testB (каким-то образом) был создан как С - dynamic_cast вернет корректный указатель на С. А откуда взялся такой testB - другой вопрос. Др. словами - работает и "вбок" скажем так. работает приведение к корректному типу не важно откуда. а по поводу "вбок" - скастить твой указатель обратно в B* просто динамиком все равно не получится))) Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: LisandreL от Марта 11, 2012, 16:16 Что у Вас печатает? У меня:testB = 00676A90, testC = 00000000 Что это доказывает? Что в разных компиляторах UB может давать разный результат. ;) Название: Re: Объясните понятно, доступно и просто как д Отправлено: Igors от Марта 11, 2012, 16:26 - скастить твой указатель обратно в B* просто динамиком все равно не получится))) И правильно не получится - ведь объекта B не было создано.Ладно, задачка для lolbla2 и др кто любит изучать экспериментируя (а не только книжки читать). Кто знает - не подсказывать Код Придумать такие классы A и B, чтобы печатались разные ненулевые указатели Название: Re: Объясните понятно, доступно и просто как д Отправлено: Авварон от Марта 11, 2012, 17:30 а не только книжки читать Это есть в любой книжке по с++ :)Название: Re: Объясните понятно, доступно и просто как д Отправлено: Igors от Марта 11, 2012, 17:37 Это есть в любой книжке по с++ :) А для начитанных есть темка чуть сложнееhttp://www.prog.org.ru/index.php?topic=21228.msg145940#msg145940 (http://www.prog.org.ru/index.php?topic=21228.msg145940#msg145940) Название: Re: Объясните понятно, доступно и просто как д Отправлено: lolbla2 от Марта 12, 2012, 09:31 - скастить твой указатель обратно в B* просто динамиком все равно не получится))) И правильно не получится - ведь объекта B не было создано.Ладно, задачка для lolbla2 и др кто любит изучать экспериментируя (а не только книжки читать). Кто знает - не подсказывать Код Придумать такие классы A и B, чтобы печатались разные ненулевые указатели Изучать экспериментируя лучше всего ИМХО, потому что не всё что написано в книжке с первого раза получается на практике... да и к тому же приходится искать книжки где то что тебе нужно достаточно подробно и понятно написано Название: Re: Объясните понятно, доступно и просто как д Отправлено: mutineer от Марта 12, 2012, 11:26 Изучать экспериментируя лучше всего ИМХО, потому что не всё что написано в книжке с первого раза получается на практике... да и к тому же приходится искать книжки где то что тебе нужно достаточно подробно и понятно написано Ну давай, дерзай решать:) Название: Re: Объясните понятно, доступно и просто как д Отправлено: LisandreL от Марта 12, 2012, 12:01 Изучать экспериментируя лучше всего ИМХО Чего греха таить, все мы иногда так поступаем.Просто не забывайте, что есть UB, которые могут по разному обрабатываться в зависимости от компилятора, ОС, их версий и настроек, а так же порой от погоды на Марсе. ;) Название: Re: Объясните понятно, доступно и просто как д Отправлено: Igors от Марта 12, 2012, 12:56 Чего греха таить, все мы иногда так поступаем. Не вижу в этом никакого "греха" :) Не призываю игнорировать теорию, но все хорошо в меру.Название: Re: Объясните понятно, доступно и просто как д Отправлено: lolbla2 от Марта 12, 2012, 18:01 Изучать экспериментируя лучше всего ИМХО Чего греха таить, все мы иногда так поступаем.Просто не забывайте, что есть UB, которые могут по разному обрабатываться в зависимости от компилятора, ОС, их версий и настроек, а так же порой от погоды на Марсе. ;) UB - Undefined behaviour ? Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: Igors от Марта 12, 2012, 18:33 UB - Undefined behaviour ? Может быть и "Universal Binary" - запоминать все возможные аббревиатуры нет смысла. А что это Вы так к (конкретным) знаниям потянулись? Экспериментировать уже расхотелось? :)Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов. Отправлено: mutineer от Марта 20, 2012, 21:10 lolbla2, так чаво с решением?
|