Comments 59
>2. dynamic_cast
>В случае неправильного приведения типов вызывается исключительная ситуация std::bad_cast и будет возвращен NULL
Как-то интересно у вас получилось, если исключение кинулось, то куда NULL тогда вернулся?
>В случае неправильного приведения типов вызывается исключительная ситуация std::bad_cast и будет возвращен NULL
Как-то интересно у вас получилось, если исключение кинулось, то куда NULL тогда вернулся?
Да, справедливо, bad_cast, вызывается только при работе со ссылками. При работе с указателями возвращается NULL
В С++ используется не NULL, а 0
да, поправил)
#ifdef __cplusplus
#define NULL 0
© stddef.h
NULL тоже используется, просто задефайнен как 0. Использую для указателей именно NULL — так наглядней, мне кажется.
#define NULL 0
© stddef.h
NULL тоже используется, просто задефайнен как 0. Использую для указателей именно NULL — так наглядней, мне кажется.
на некоторых платформах NULL это -1
а -1 это всегда число, а 0 тип контекстнозависим
а -1 это всегда число, а 0 тип контекстнозависим
мне кажется это FALSE на некоторых платформах (базы данных, например, может не все) равен -1, а не NULL. Можно пример, чтоб я понял, что я ошибаюсь?
не FALSE, а TRUE, конечно.
в С нет boolean'а. Для if, while, и так далее используются целочисленный типы: нуль/не нуль
в С++ все же приводится к типу boolean:
* целочисленный приводятся нуль/не нуль
* указатели: валидный/невалидный
Опять же в С указатели — это фактически целочисленные типы (хотя это очень приблеженно) — но в любом случае они приводятся к целому. В С++ они к целому не приводятся, а только к boolean'у
Не надо путать физическое значение, и логическое, которое в С++ куда более важно
в С++ все же приводится к типу boolean:
* целочисленный приводятся нуль/не нуль
* указатели: валидный/невалидный
Опять же в С указатели — это фактически целочисленные типы (хотя это очень приблеженно) — но в любом случае они приводятся к целому. В С++ они к целому не приводятся, а только к boolean'у
Не надо путать физическое значение, и логическое, которое в С++ куда более важно
Всегда интересовал вопрос, чем при использовании C++ отличается reinterpret_cast и C-style cast?
по сути ничем
Вот здесь www.rsdn.ru/forum/cpp/3812985.aspx почитайте
reinterpret_cast, например не снимает константность
Например, при касте к одному из предков, участвовавших в множественном наследовании, reinterpret_cast не сдвинет указатель (и он станет невалидным), а си-стайл каст сдвинет.
обновил статью — насчет порядка вызова cast-ов при C-Style cast
ой-ой.
вовремя я ушёл в javascript с плюсов :)
язык должен помогать решать задачу, а не ломать себе мозг
вовремя я ушёл в javascript с плюсов :)
язык должен помогать решать задачу, а не ломать себе мозг
Зря вы так… Адепты объектно-ориентированного проектирования, включая меня, вас сотрут в порошок :)
ЗЫ Поставил плюсик вашему комментарию, но это, судя по всему вас все равно не спасет :)
ЗЫ Поставил плюсик вашему комментарию, но это, судя по всему вас все равно не спасет :)
Обнаружена холивар-вероятная точка. Каждый язык хорош для своей области.
ООП != C++ Можно быть адептом ООП и не ломать себе мозг выбором способа приведения типов
UFO just landed and posted this here
Не все задачи можно на javascript-е решить)
Если для вас это ломка мозга, то зачем вы вообще в программисты пошли? Вы не знаете чем отличается статическая от динамической типизации?
Друзья, я и не думал холиварить :)
Это была всего лишь внезапная эмоция, которой я счёл уместным поделиться, скорее даже в качестве иронии. Так сложилось, что за c++ мне нынче остаётся только наблюдать. А может даже в тайне ото всех я мечтаю когда-нибудь вернуться ;)
Это была всего лишь внезапная эмоция, которой я счёл уместным поделиться, скорее даже в качестве иронии. Так сложилось, что за c++ мне нынче остаётся только наблюдать. А может даже в тайне ото всех я мечтаю когда-нибудь вернуться ;)
пацаны, зацените мой юмор:
#define c_dynamic_cast(__struct,__field,__ptr) ((__struct*)&(((char*)__ptr)[(char*)0 - (char*)&((__struct*)0)->__field]))
dynamic_cast — это не такая тривиальная функция. Ей для работы необходимо, грубо говоря, по дереву RTTI проходить. В compile-time это не решается.
поэтому отнес к юмору, поскольку в Си (речь про Си без плюсов, иначе как бы зачем макрос?), работы с наследованием структур нет. Макрос может пригодится, когда из указателя на поле нужно получить указатель на заголовок структуры. Не хотел никак покушаться на нетривиальность Си++ ;)
А почему вы её назвали «dynamic_cast»? В С++ dynamic_cast делает совсем другое.
Чтобы запутать того, кто потом код читать будет?
Чтобы запутать того, кто потом код читать будет?
Во первых не «dynamic_cast», а «c_dynamic_cast», как бы намекая. Во вторых, если например в структуре используется вложение:
struct child {
struct parent head; // Как это в том же конкуренте топика — gobject
struct field1 field1;
…
struct fieldN fieldN;
};
то приведение типов:
struct parent* p = getSome();
struct child* c = (struct child*)p;
будет менее предпочтительней, чем
struct parent* p = getSome();
struct child* c = c_dynamic_cast(struct child, head, p);
поскольку перед head может быть встрена, скажем, структура отладки, или структура выравнивания. Вот чем руководствовался:
— «dynamic» — динамическое;
— «cast» — приведение типа.
В них не скрывается сакрального смысла. Во всяком случае угловые скобки все расставят по местам.
struct child {
struct parent head; // Как это в том же конкуренте топика — gobject
struct field1 field1;
…
struct fieldN fieldN;
};
то приведение типов:
struct parent* p = getSome();
struct child* c = (struct child*)p;
будет менее предпочтительней, чем
struct parent* p = getSome();
struct child* c = c_dynamic_cast(struct child, head, p);
поскольку перед head может быть встрена, скажем, структура отладки, или структура выравнивания. Вот чем руководствовался:
— «dynamic» — динамическое;
— «cast» — приведение типа.
В них не скрывается сакрального смысла. Во всяком случае угловые скобки все расставят по местам.
Я давно уже програмлю на плюсах, и давно уже програмлю только на С( так как часть работы сидела я линукс кернел).
И на самом деле уже два года это уже не моя работа.
Но я никогда не применял эти касты и не понимал зачем они нужны, и зачем их придумали — тоже не принимал.
И за 10( а то и больше) лет, у меня никогда не было проблем с кастами, приведением типов и виртуальными методами.
Других багов было много, и магия была и не шаманства.
Но старый добрый CBase base=(CBase)сhild; меня никогда не подводил
И на самом деле уже два года это уже не моя работа.
Но я никогда не применял эти касты и не понимал зачем они нужны, и зачем их придумали — тоже не принимал.
И за 10( а то и больше) лет, у меня никогда не было проблем с кастами, приведением типов и виртуальными методами.
Других багов было много, и магия была и не шаманства.
Но старый добрый CBase base=(CBase)сhild; меня никогда не подводил
>Но старый добрый CBase base=(CBase)сhild; меня никогда не подводил
Разве это не будет сделано автоматически без ручного приведения типов? Приведение типов сверху вниз очень полезно при разработке gui приложений, впрочем любовь к ним говорит о недостатках дизайна.
Разве это не будет сделано автоматически без ручного приведения типов? Приведение типов сверху вниз очень полезно при разработке gui приложений, впрочем любовь к ним говорит о недостатках дизайна.
Это я образно. Вообще приведение будет произведено при добавлении в какой либо контейнер.
Просто потому что любой контейнер — что монстров на уровне, что элементов этого ГУЯ( который есть одно из мест где возможны самые интересные применения ООП и приведения разностных типов к единому «работельному» состоянию) — так вот этот контейнер строго типизирован( не строго типизироавный контейнер на самом деле тоже строго типизирован. но его тип не строго следит за тем что в него внутрях и позволяет различные вольности, так что к этой фразе особо не придерайтесь)
Просто потому что любой контейнер — что монстров на уровне, что элементов этого ГУЯ( который есть одно из мест где возможны самые интересные применения ООП и приведения разностных типов к единому «работельному» состоянию) — так вот этот контейнер строго типизирован( не строго типизироавный контейнер на самом деле тоже строго типизирован. но его тип не строго следит за тем что в него внутрях и позволяет различные вольности, так что к этой фразе особо не придерайтесь)
Вопрос по существу, насколько оправдано юзание dynamic_cast'ов в Qt. И еще есть, как минимум, еще два вида кастов
qdbus_cast,qstyleoption_cast
qdbus_cast,qstyleoption_cast
Использование dynamic_cast-ов в большинстве своем не оправдано. Во-первых сами тролли, если посмотреть по коду, не используют dynamic_cast и RTTI, во-вторых функции RTTI в основном берет на себя Meta System.
Есть еще qgraphicsitem_cast и qscriptvalue_cast, я просто рассмотрел два наиболее мною используемых
Есть еще qgraphicsitem_cast и qscriptvalue_cast, я просто рассмотрел два наиболее мною используемых
хорошо, а как мне лучше тогда такую проблему обойти?
Есть некий абстрактный класс
Но его реализация должна представлять собой QWebPage, в итоге получается
Таким образом, контроллер невозможно унаследовать от QObject'а, не говоря даже о том, что возможен случай, в котором контроллер просто не будет вообще никаким местом связан с QObject'ом.
В итоге я не могу пользоваться qobject_cast'ами. А без множественного наследования я получаю весьма сложный код.
Есть некий абстрактный класс
class ChatViewController
Но его реализация должна представлять собой QWebPage, в итоге получается
class ChatStyleOutput : public QWebPage, public ChatViewController
Таким образом, контроллер невозможно унаследовать от QObject'а, не говоря даже о том, что возможен случай, в котором контроллер просто не будет вообще никаким местом связан с QObject'ом.
В итоге я не могу пользоваться qobject_cast'ами. А без множественного наследования я получаю весьма сложный код.
А зачем вообще в этом случае кастовать «вниз» — от интерфейса к реализации?
Нет, ну это всего лишь рекомендация. Следовать ей или нет решать, собственно, программисту, который использует их библиотеку. Если использование dynamic_cast-а необходимо, то его надо использовать.
Такая же ситуация, например, с применением обработки исключений. Трольтех рекомендует проверять возвращаемое значение, но если основная часть кода написана с применением обработки, то имеет смысл не нарушать общий стиль процесса разработки проекта.
Такая же ситуация, например, с применением обработки исключений. Трольтех рекомендует проверять возвращаемое значение, но если основная часть кода написана с применением обработки, то имеет смысл не нарушать общий стиль процесса разработки проекта.
Меня больше интересуют возможности обхода этой проблемы Qtшными средствами, чтобы прога работала при выключенном RTTI
а почему в данном случае нельзя использовать static_cast?
А если классы будут в разных библиотеках?
у меня есть интересные разработки, который использует исключения. так вот там dynamic cast очень много встречается. но так как это использует цикл обработки сообщений — то это не медленно
спасибо, на си++ не пишу, но всегда было интересно, что все это значит
добавлю статью в избранное
добавлю статью в избранное
Хочу немного дополнить:
1. const_cast также умеет добавлять cv-квалификаторы
2. для преобразования указателей лучше использовать двойной static_cast через void* вместо reinterpret_cast
или вот такой pointer_cast
1. const_cast также умеет добавлять cv-квалификаторы
2. для преобразования указателей лучше использовать двойной static_cast через void* вместо reinterpret_cast
или вот такой pointer_cast
/// This template functions should be used when we perform cast from one pointer type to another
/// It's safer than using reiterpret_cast
///
/// It doesn't allow to do such things like:
/// int i = 10;
/// A *a = pointer_cast<A*>(i);
/// Only pointer could be used in this function.
template<typename result, typename source>
result pointer_cast(source *v)
{
return static_cast<result>(static_cast<void*>(v));
}
template<typename result, typename source>
result pointer_cast(const source *v)
{
return static_cast<result>(static_cast<const void*>(v));
}
спасибо. насчет добавления cv-квалификаторов знал, забыл упомянуть, а про преобразование через void* — отличное пояснение:
> /// It's safer than using reiterpret_cast
>///
>/// It doesn't allow to do such things like:
>/// int i = 10;
>/// A *a = pointer_cast<A*>(i);
>/// Only pointer could be used in this function.
> /// It's safer than using reiterpret_cast
>///
>/// It doesn't allow to do such things like:
>/// int i = 10;
>/// A *a = pointer_cast<A*>(i);
>/// Only pointer could be used in this function.
static_cast так же умеет работать со ссылками и указателями, и с любыми типами, содержащими виртуальные члены, например, не обязательно статический тип.
pastebin.org/251996
Разница в работе.
pastebin.org/251996
Разница в работе.
Sign up to leave a comment.
Приведение типов