Russian Qt Forum

Программирование => Общий => Тема начата: lolbla2 от Марта 06, 2012, 19:33



Название: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: lolbla2 от Марта 06, 2012, 19:33
Звачем нужны dynamic_cast, static_cast, reinterpret_cast, qobject_cast и т д?
Сколько статей читал, толком суть не понял чот((
Ведь вроде можно проще приводить к типам. например

Код
C++ (Qt)
int x=9;
float y= (float)x;
 

а между float и double вообще неявное приведение, то есть можно прям вот так:

Код
C++ (Qt)
float x=3.231;
double g=x; //неявно приводится к double
 


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: Igors от Марта 06, 2012, 19:57
Ну вообще-то форум - не для изучения основ, та что придется отправлять на гугл  :) Просто наберите напр static_cast C++ попадете на Алену, девушка доходчиво пишет. Обижаться на форумчан не надо, никому не охота переписывать гугл - а ответ на этот вопрос может быть только таким.

По поводу простых типов. Если 2 типа совместимы по присваиванию, то один из них всегда "старше" а др "младше".  Если младший присваивается старшему, никакие приведения не нужны. Примеры

Код
C++ (Qt)
float f = 0.5f;
double d = 2.1;
int i1, i2;
 
f = i1;     // float "старше" int, все норм
f = d;     // а здесь double старше, компилятор может вякнуть варнингом
f = (float) d;  // сказали компилятору что согласны с потерей точности
 
// результат арифметики возвращается как старший тип
i1 = 2;
i2 = 3;
d = (i1 + i2) / 2;   // результат d = 2.0;
d = (i1 + i2) / 2.0;   // результат d = 2.5;
 


Название: 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 может приводить и не только родителя к потомку
Код
C++ (Qt)
class A {..};
class B : public A {..};
class C : public A {..};
...
B * b = ..
C * c = dynamic_cast <C *> b;
// с - нормальный указатель на объект класса С (если он был таким создан)
 


Название: 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 типа совместимы по присваиванию, то один из них всегда "старше" а др "младше".  Если младший присваивается старшему, никакие приведения не нужны. Примеры

Код
C++ (Qt)
float f = 0.5f;
double d = 2.1;
int i1, i2;
 
f = i1;     // float "старше" int, все норм
f = d;     // а здесь double старше, компилятор может вякнуть варнингом
f = (float) d;  // сказали компилятору что согласны с потерей точности
 
// результат арифметики возвращается как старший тип
i1 = 2;
i2 = 3;
d = (i1 + i2) / 2;   // результат d = 2.0;
d = (i1 + i2) / 2.0;   // результат d = 2.5;
 

То есть эти все ..._cast для того чтобы совершать преобразование типов между без потери данных, я так понимаю, верно?

Кстати, а если попоробовать преобразовать  не связанные никак типы, то есть:
Код
C++ (Qt)
class A{....};
class B{...};
 
A * typeA;
B *typeB;
B = dynamic_cast<*B> typeA; // dynamic_cast вернёт NULL?
 


Название: 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 показывает это четко, рельефно

Кстати, а если попоробовать преобразовать  не связанные никак типы, то есть:
Код
C++ (Qt)
B = dynamic_cast<*B> typeA; // dynamic_cast вернёт NULL?
 
До этого дело не дойдет, компилятор не пропустит. А вот приведение (B *) в С стиле пройдет - и потом найти концы может быть непросто


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: lolbla2 от Марта 11, 2012, 12:31
Хотелось бы понять ещё некоторые тонкости:

Код
C++ (Qt)
class A{
public:
int e;
}
class B: public A
{
public:
double h;
}
 
.....
// делаем вот тут такое
A* vA = new A;
vA->e=3;
B* vB= dynamic_cast<*B> vA;
// собственно вопрос: какие будут значения полей у vB, т.е. vB.e, vB.h какие будут иметь значения?
// то есть при преобразовании типо их поля как друг другу передаются?
 
...
 
 

а наоборот если, то тогда что?

Код
C++ (Qt)
B* vB = new B;
vB.h= 2.345;
vB.e=1;
A *vA = dynamic_cast<*A> vB;
// каким будет значение в vA.e ?
 


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: Пантер от Марта 11, 2012, 12:42
vB.e будет 3.
vB.h не определено.
Наоборот, h потеряется, произойдет "срезка". e останется 1.


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: Igors от Марта 11, 2012, 12:43
Код
C++ (Qt)
.....
// делаем вот тут такое
A* vA = new A;
vA->e=3;
B* vB= dynamic_cast<*B> vA;
// собственно вопрос: какие будут значения полей у vB, т.е. vB.e, vB.h какие будут иметь значения?
// то есть при преобразовании типо их поля как друг другу передаются?
 
...
 
 
Не происходит никакой "передачи/копирования". dynamic_cast разберется что vA был создан как "А" (а не как "B") и вернет NULL

Код
C++ (Qt)
а наоборот если, то тогда что?
 
B* vB = new B;
vB.h= 2.345;
vB.e=1;
A *vA = dynamic_cast<*A> vB;
// каким будет значение в vA.e ?
 
Здесь никакое приведение не нужно т.к. известно что B порожден от A. Значение "e" будет тем же что установили, и адреса vA и vB будут равны

А книжки все-таки надо читать (ну иногда  :))


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: lolbla2 от Марта 11, 2012, 13:02
dynamic_cast - приведение указателей на классы из одной иерархии (указатель на родителя к указателю на потомка и наоборот); проверка на корректность приведение выполняется всегда (в процессе выполнения программы), некорректное приведение не выполняется
Ну если уж вдаваться в тонкости, то dynamic_cast может приводить и не только родителя к потомку
Код
C++ (Qt)
class A {..};
class B : public A {..};
class C : public A {..};
...
B * b = ..
C * c = dynamic_cast <C *> b;
// с - нормальный указатель на объект класса С (если он был таким создан)
 

Кажется ты меня чуток обманул, родителя к потому нельзя приводить, только наоборот потомка можно к родителю привести. Щас попробовал, при приведении таком:
Код
C++ (Qt)
class A{
public:
   int e;
   virtual void func();
};
void A::func()
{
   e=3;
}
 
class B: public A
{
public:
   double h;
};
 
int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);
 
   B* vB = new B;
   vB->h= 2.345;
   vB->e=14;
   A *vA = dynamic_cast<A*> (vB);
   qDebug() << vA->e;
   return a.exec();
} //Всё ок vA->e=14;
 

Но при таком преобразовании:
Код
C++ (Qt)
   A* vA = new A;
   vA->e = 34;
   B* vB = dynamic_cast<B*> (vA); //dynamic_cast вернул NULL
   qDebug() << vB;
 

Что говорит о том, что нельзя папу преобразовать к сыну  ;D


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: Igors от Марта 11, 2012, 13:22
...
Что говорит о том, что нельзя папу преобразовать к сыну  ;D
Он ведь dynamic  :)

Код
C++ (Qt)
   A * vA = new A();
   B* vB = dynamic_cast<B*> (vA); //dynamic_cast вернул NULL
 
   vA = new B();
   vB = dynamic_cast<B*> (vA); //  а теперь уже не NULL
 


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: lolbla2 от Марта 11, 2012, 13:28
...
Что говорит о том, что нельзя папу преобразовать к сыну  ;D
Он ведь dynamic  :)

Код
C++ (Qt)
   A * vA = new A();
   B* vB = dynamic_cast<B*> (vA); //dynamic_cast вернул NULL
 
   vA = new B();
   vB = dynamic_cast<B*> (vA); //  а теперь уже не NULL
 

ммм.... как здорово, оказывается надо знать такие чёткие тонкости. Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть

Код
C++ (Qt)
vA = new B();
vB = dynamic_cast<B*> (vA); // у класса B есть поля которых нет у А, значит в  vB.h находится мусор, и также было бы с другими полями если бы они были да?
 

P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?)


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: mutineer от Марта 11, 2012, 13:32
ммм.... как здорово, оказывается надо знать такие чёткие тонкости. Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть

Код
C++ (Qt)
vA = new B();
vB = dynamic_cast<B*> (vA); // у класса B есть поля которых нет у А, значит в  vB.h находится мусор, и также было бы с другими полями если бы они были да?
 

P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?)

не будет там никакого мусора - при new B() конструктор класса B инициализировал (если в нем прописана эта инициализация, конечно) все поля объекта класса В


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: qt_user от Марта 11, 2012, 13:43
ммм.... как здорово, оказывается надо знать такие чёткие тонкости. Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть

Код
C++ (Qt)
vA = new B();
vB = dynamic_cast<B*> (vA); // у класса B есть поля которых нет у А, значит в  vB.h находится мусор, и также было бы с другими полями если бы они были да?
 

P.S. не подскажешь книгу или статью где описаны всякие такие тонкости?)

vA это всего лишь указатель на объект класса В и не больше, тонкость состоит только
в том что класс А ничего не знает о "новых" полях класса В и указатель на класс А собственно
тоже в таком случае чтобы получить доступ к полю h надо сделать приведение:
Код:
vA = new B();
(vB *)vA->h;

p.s: доходчиво написано у Шилдта и конечно же документация:
http://www.cplusplus.com/doc/tutorial/typecasting/ там все разжевано


Название: Re: Объясните понятно, доступно и просто как для чайника про приведение типов.
Отправлено: Igors от Марта 11, 2012, 13:44
Значит получается, при преобразовании от родителя к потомку все поля, которых у родителя нет после преобразования будут иметь "мусор" ? То есть

Код
C++ (Qt)
vA = new B();
vB = dynamic_cast<B*> (vA); // у класса B есть поля которых нет у А, значит в  vB.h находится мусор, и также было бы с другими полями если бы они были да?
 
Знову за рибу грош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
чуток изменил иерархию классов
Код
C++ (Qt)
class A{
public:
   int e;
   virtual void func();
};
void A::func()
{
   e=3;
}
 
class B: public A
{
public:
   double h;
};
 
class C: public A
{
public:
   int c;
};
 

как теперь привести от B к С?

Код
C++ (Qt)
A* vA = new B;
   vA->e = 34;
   B* vB = dynamic_cast<B*> (vA);
   qDebug() << vB->e<<" "<< vB->h<<endl;
 
 
   C* vC = dynamic_cast<C*> (vB); // так NULL  :(
   qDebug() << vC;
 


Название: 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* не может легально указывать на объект класса В

Ясно, значит нельзя...

а вот при такой иерархии:
Код
C++ (Qt)
class A{
public:
   int e;
   virtual void func();
};
void A::func()
{
   e=3;
}
 
class B: public A
{
public:
   double h;
};
 
class C: public B
{
public:
   int 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
а вот при такой иерархии:
Код
C++ (Qt)
class A{
public:
   int e;
   virtual void func();
};
void A::func()
{
   e=3;
}
 
class B: public A
{
public:
   double h;
};
 
class C: public B
{
public:
   int c;
};
 

можно от С к А? от А к С?

мы же говорим про 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 не является указателем на С или его наследник.
Давайте проверим
Код
C++ (Qt)
#include <QtGui>
 
struct A {
int testA;
 
virtual int Test( void ) { return 0; }
};
 
struct B : public A {
int testB;
 
virtual int Test( void ) { return 1; }
};
 
struct C : public A {
int testC;
 
virtual int Test( void ) { return 2; }
};
 
C * TestCast2C( B * testB )
{
return dynamic_cast <C *> (testB);
}
 
int main(int argc, char **argv)
{
B * testB = (B *) new C();
C * testC = TestCast2C(testB);
printf("testB = %p, testC = %p\n", testB, testC);
return 0;
}
 
Что у Вас печатает?


Название: Re: Объясните понятно, доступно и просто как д
Отправлено: mutineer от Марта 11, 2012, 15:51
Что у Вас печатает?

Мы тут говорим про кастование через dynamic_cast, а ты читеришь используя C-style cast
Код
C++ (Qt)
B * testB = (B *) new C();

При этом testB указывает на С, но пользоваться таким указателем очень чревато


Название: Re: Объясните понятно, доступно и просто как д
Отправлено: Igors от Марта 11, 2012, 16:05
Мы тут говорим про кастование через dynamic_cast, а ты читеришь используя C-style cast
Я тоже о нем говорю
Код
C++ (Qt)
C * TestCast2C( B * testB )
{
return dynamic_cast <C *> (testB);
}
 
Если testB (каким-то образом) был создан как С - dynamic_cast вернет корректный указатель на С. А откуда взялся такой testB - другой вопрос. Др. словами - работает и "вбок" 


Название: Re: Объясните понятно, доступно и просто как д
Отправлено: mutineer от Марта 11, 2012, 16:15
Мы тут говорим про кастование через dynamic_cast, а ты читеришь используя C-style cast
Я тоже о нем говорю
Код
C++ (Qt)
C * TestCast2C( B * testB )
{
return dynamic_cast <C *> (testB);
}
 
Если 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 и др кто любит изучать экспериментируя (а не только книжки читать).
Кто знает - не подсказывать

Код
C++ (Qt)
...
B * pB = dynamc_cast <B *> (pA);
printf("pA = %p, pB = %p\n", pA, pB);
 
Придумать такие классы 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 и др кто любит изучать экспериментируя (а не только книжки читать).
Кто знает - не подсказывать

Код
C++ (Qt)
...
B * pB = dynamc_cast <B *> (pA);
printf("pA = %p, pB = %p\n", pA, pB);
 
Придумать такие классы 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, так чаво с решением?