... десять минут назад этого форума ещё не было :o)
Ok, тогда вопрос, давно хотел спросить.
Кто из почтенной публики использует операторы *_cast, кроме dynamic_cast (без него иногда не обойтись), в реальных проектах? И зачем?
Happy coding,
Игорь.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте IT, 25.04.2001 19:40:19 вы писали:
>Кто из почтенной публики использует операторы *_cast, кроме dynamic_cast (без него иногда не обойтись), в реальных проектах? И зачем? > >Happy coding, >Игорь.
Я как-то раз использовал. Зачем? Моча в голову стукнула.
Здравствуйте IT, 25.04.2001 19:40:19 вы писали:
>Кто из почтенной публики использует операторы *_cast, >кроме dynamic_cast (без него иногда не обойтись), в >реальных проектах? И зачем?
Я стараюсь вообще перейти именно на такие способы приведения
типа поскольку они безопаснее.
О них очень хорошо написано в книге Scott Meyers "More Effective C++"
(к сожалинию потерял ссылочку на онлайновый вариант, может кто подскажет?)
Он в своей книге страшно нахваливает эти способы преобразования типов, приводя уйму доводов "за".
Например:
— использование static_cast предохраняет тебя от изменения const переменной
— использование static_cast предохраняет тебя от несовместимого приведения типа указателя
— используя const_cast и reinterpret_cast ты явно указывешь что в этом месте ты выходишь
за установленные рамки, что делает текст программы более понятным.
в общем советую почитать эту книжечку и решить самому, нужно тебе это или нет.
Здравствуйте IT, 25.04.2001 19:40:19 вы писали:
>... десять минут назад этого форума ещё не было :o) > >Ok, тогда вопрос, давно хотел спросить. >Кто из почтенной публики использует операторы *_cast, кроме dynamic_cast (без него иногда не обойтись), в реальных проектах? И зачем? > >Happy coding, >Игорь.
Цитата из Bjarne Stroustrup:
"C++ унаследовал от С форму записи (T)e, означающую любое преобразование, которое может быть выражено комбинацией static_cast, reinterpret_cast, const_cast, для получения значетия типа T из выражения e. Такой стиль намного опаснее, чем именованные операторы преобразования, потому что преведенную форму записи сложнее отслеживать в большой программе и вид преобразования, который имел ввиду программист не очевиден."
Здравствуйте IT, 25.04.2001 19:40:19 вы писали:
>... десять минут назад этого форума ещё не было :o)
просто звери ;)
>Ok, тогда вопрос, давно хотел спросить. >Кто из почтенной публики использует операторы *_cast, кроме dynamic_cast (без него иногда не обойтись), в реальных проектах? И зачем?
const_cast пришлось пару раз поюзать — функция хотела указатель не на константу (в обоих случаях я был уверен что в этой памяти (с которой сняли константность) ничего не будет изменятся ...
ну а reinterpret_cast & static_cast — они-ж как братья — если не один то другой ...
а dynamic_cast<> — это наша обсчая Ж...
(ксати буквально седня столкнулся с проблемой в VC6 — у мя есть иерархия высотой 3-4 класса — наследование от темплейтных классов (и не только) — но наследование одиночное) — и
dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... что под указателем лежит нунжый обект — 100% (во первых так оно и есть вот вторых виртуалтные метобы вызываются прально).
>dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... следует читать как
dynamic_cast — не смог мне откастить (получал NULL pointer) — а reinterpret_cast помог ...
Здравствуйте igor_soukhov, 26.04.2001 02:30:36 вы писали:
>>dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... следует читать как >dynamic_cast — не смог мне откастить (получал NULL pointer) — а reinterpret_cast помог ... >
А почему это? Может ты RTTI забыл включить?
Если нам не помогут, то мы тоже никого не пощадим.
>Здравствуйте igor_soukhov, 26.04.2001 02:30:36 вы писали:
>>>dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... следует читать как >>dynamic_cast — не смог мне откастить (получал NULL pointer) — а reinterpret_cast помог ... >>
>А почему это? Может ты RTTI забыл включить?
Вот будет свободное время (или падать на этом месте ;) — попробую разобраться ...
А RTTI конечно включено — всетаки приходится пользовать dcast иногда ...
Здравствуйте igor_soukhov, 26.04.2001 01:56:36 вы писали:
>(ксати буквально седня столкнулся с проблемой в VC6 — у мя есть иерархия высотой 3-4 класса — наследование от темплейтных классов (и не только) — но наследование одиночное) — и >dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... что под указателем лежит нунжый обект — 100% (во первых так оно и есть вот вторых виртуалтные метобы вызываются прально).
Скорее всего ты пытался привести dynamic_cast'ом указатель к классу не имеющему ниодной виртуальной функции при выключеной в опциях проекта RTTI.
Привет Андрей,
>>(ксати буквально седня столкнулся с проблемой в VC6 — у мя есть иерархия высотой 3-4 класса — наследование от темплейтных классов (и не только) — но наследование одиночное) — и >>dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... что под указателем лежит нунжый обект — 100% (во первых так оно и есть вот вторых виртуалтные метобы вызываются прально).
>Скорее всего ты пытался привести dynamic_cast'ом указатель к классу не имеющему ниодной виртуальной
функции при выключеной в опциях проекта RTTI.
во первых я писал что ВИРТУАЛЬНЫЕ методы работают ! :)
во вторых — то что ты описал — проверяется в complile-time ... то есть просто бы не скомпилилось...
завтра нарисую иерархию наследования — может че проясним ...
>С наилучшими, >Андрей.
Здравствуйте igor_soukhov, 26.04.2001 07:59:47 вы писали:
Hi !
В общем я был неправ ... ;(
иерархия классов такова
СSnapInItem(ATL)
^
|
CSnapInItemImpl<T> : public СSnapInItem
^
|
CXXXData<T> : public CSnapInItemImpl<T>
^
|
CResultNode<T> :public CXXXData<T>
^
|
CResultNodeNum<T> : public CResultNode<T>
^
|
CConcreteResultNode : CResultNodeNum<CConcreteResultNode>
указатель p — указывает на обект CConcreteResultNode...
статический тип указателя p — CSnapInItem .... я его хочу привести к
СResultNode<CConcreteResultNode>... В СResultNode есть v-метод, кооторый
мне надо вызвавть(этот метод переопределяется в CConcreteResultNode).
в это приведения я делал из metoda другого темплейтного класса ...
код там был такой:
СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p);
естественно что T в этом методе — это не CConcreteResultNode посему и был облом ...
Best regards,
Igor
>Привет Андрей, > >>>(ксати буквально седня столкнулся с проблемой в VC6 — у мя есть иерархия высотой 3-4 класса — наследование от темплейтных классов (и не только) — но наследование одиночное) — и >>>dynamic_cast — не смог мне откастить (получал NULL pointer) — а (T*) преобразование помогло ... что под указателем лежит нунжый обект — 100% (во первых так оно и есть вот вторых виртуалтные метобы вызываются прально). > >>Скорее всего ты пытался привести dynamic_cast'ом указатель к классу не имеющему ниодной виртуальной >функции при выключеной в опциях проекта RTTI. >во первых я писал что ВИРТУАЛЬНЫЕ методы работают ! :) >во вторых — то что ты описал — проверяется в complile-time ... то есть просто бы не скомпилилось... >завтра нарисую иерархию наследования — может че проясним ... > >>С наилучшими, >>Андрей. > >Пасиба, >Igor
>указатель p — указывает на обект CConcreteResultNode... >статический тип указателя p — CSnapInItem .... я его хочу привести к >СResultNode<CConcreteResultNode>... В СResultNode есть v-метод, кооторый >мне надо вызвавть(этот метод переопределяется в CConcreteResultNode). > >в это приведения я делал из metoda другого темплейтного класса ... >код там был такой: >СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); > >естественно что T в этом методе — это не CConcreteResultNode посему и был облом ... > >Best regards, >Igor >
вместо СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p);
не пробовал использовать
СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T>* >(p);
Здравствуйте ILYA_Varchev, 27.04.2001 08:13:50 вы писали:
>>указатель p — указывает на обект CConcreteResultNode... >>статический тип указателя p — CSnapInItem .... я его хочу привести к >>СResultNode<CConcreteResultNode>... В СResultNode есть v-метод, кооторый >>мне надо вызвавть(этот метод переопределяется в CConcreteResultNode). >> >>в это приведения я делал из metoda другого темплейтного класса ... >>код там был такой: >>СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); >> >>естественно что T в этом методе — это не CConcreteResultNode посему и был облом ... >> >>Best regards, >>Igor >> >вместо СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); >не пробовал использовать >СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T>* >(p); > >может поможет.
это очепятка была ;)
Здравствуйте igor_soukhov, 27.04.2001 10:12:11 вы писали:
>Здравствуйте ILYA_Varchev, 27.04.2001 08:13:50 вы писали: > >>>указатель p — указывает на обект CConcreteResultNode... >>>статический тип указателя p — CSnapInItem .... я его хочу привести к >>>СResultNode<CConcreteResultNode>... В СResultNode есть v-метод, кооторый >>>мне надо вызвавть(этот метод переопределяется в CConcreteResultNode). >>> >>>в это приведения я делал из metoda другого темплейтного класса ... >>>код там был такой: >>>СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); >>> >>>естественно что T в этом методе — это не CConcreteResultNode посему и был облом ... >>> >>>Best regards, >>>Igor >>> >>вместо СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); >>не пробовал использовать >>СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T>* >(p); >> >>может поможет. >это очепятка была ;) > >Igor >
dyn_cast совершенно правильно работает — например СResultNode<T1> и СResultNode<T2> совершенно разные типы и dynamic_cast выдаст NULL при попыке преобразовать один тип к другому. Однако код вида:
будет, ВОЗМОЖНО, работать правильно, пока ты не будешь использовать переменные-члены класса
СResultNode<T2>.
Похожий код я встречал в MFC. Я думаю, что все знают класс CListView и у него функцию GetListCtrl()...Так вот эта функция реализована вот так:
CListCtrl& CListView::GetListCtrl()
{
return *( ( CListCtrl* ) this );
}
почему это работает? Да потому что у CListCtrl НЕТ ДАННЫХ. Всё что нужно CListCtrl — это CWnd::m_hWnd. А эта переменная определана у общего родителя — CWnd; именно поэтому всё и работает.
Возможно нечто подобное происходит и у тебя в коде :=)
>>>dynamic_cast — не смог мне откастить (получал NULL pointer) — а reinterpret_cast помог ...
Ну дык значит преобразование невозможно (или невозможно напрямую). reinterpret_cast — это "дубовое преобразование", типа размеры совпадают — и все. dynamic_cast, по-моему, выполняет только upcasting и downcasting, то есть невозможно преобразовать один тип к другому, если они оба порождены от одного класса, но ни один из них не является потомком другого — тогда преобразовывай сперва к общему предку, а потом — к нужному.
А reinterpret_cast тебя спасет, только за последствия не отвечаю.
Здравствуйте ILYA_Varchev, 27.04.2001 11:43:07 вы писали:
>>>>указатель p — указывает на обект CConcreteResultNode... >>>>статический тип указателя p — CSnapInItem .... я его хочу привести к >>>>СResultNode<CConcreteResultNode>... В СResultNode есть v-метод, кооторый >>>>мне надо вызвавть(этот метод переопределяется в CConcreteResultNode). >>>> >>>>в это приведения я делал из metoda другого темплейтного класса ... >>>>код там был такой: >>>>СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); >>>> >>>>естественно что T в этом методе — это не CConcreteResultNode посему и был облом ... >>>> >>>>Best regards, >>>>Igor >>>> >>>вместо СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T> >(p); >>>не пробовал использовать >>>СResultNode<T> *pConcrecteResultNode = dynamic_cast<СResultNode<T>* >(p); >>> >>>может поможет. >>это очепятка была ;) >> >>Igor >> > >dyn_cast совершенно правильно работает — например СResultNode<T1> и СResultNode<T2> совершенно разные типы и dynamic_cast выдаст NULL при попыке преобразовать один тип к другому. Однако код вида:
СResultNode<CConcreteResultNode> это базовый класс для моего CConcreteResultNode... к
нему я и пытался привести... (проблема была в том что этот кастинг проводился был в методе
СОВСЕМ другого ТЕМПЛЕЙТНОГО класса (и T там обозначало не CConcreteResultNode) ...
>СResultNode<T2> *p2; >..... >СResultNode<T1> *p1 = ( СResultNode<T1>*) p2; >p1 ->Method1(...); >p1 ->Method2(...); > >будет, ВОЗМОЖНО, работать правильно, пока ты не будешь использовать переменные-члены класса >СResultNode<T2>. >Похожий код я встречал в MFC. Я думаю, что все знают класс CListView и у него функцию GetListCtrl()...Так вот эта функция реализована вот так: >CListCtrl& CListView::GetListCtrl() >{ > return *( ( CListCtrl* ) this ); >} >почему это работает? Да потому что у CListCtrl НЕТ ДАННЫХ. Всё что нужно CListCtrl — это CWnd::m_hWnd. А эта переменная определана у общего родителя — CWnd; именно поэтому всё и работает. > >Возможно нечто подобное происходит и у тебя в коде :=)
возможно ...
>Успехов!
Пасиба,
Igor