Выход на вашей машине, возможно, был «один один», но он мог так же легко взорваться, ушел & достал вам мороженое или запустил ракеты. Ваш код вызывает Undefined Behavior.
class one
/*...*/
class two
/*...*/
Обратите внимание, что one
и two
совершенно не связанных между собой классов. Вы не получаете two
от one
, или наоборот. Они совершенно разные.
Из-за этого ...
two dp[3];
one *bp = (one *)dp;
for (int i=0; i<3;i++)
(bp++)->out();
Этот код вызывает неопределенное поведение *.bp
не указывает на объект типа one
, он указывает на объект типа two
. Вы не можете бросать указатели таким образом, учитывая приведенный выше код.
(* Примечание:.. Неопределенное поведение было, когда вы пытались вызвать метод, когда объект был фактически two
one
Кастинг себя не вызывает неопределенное поведение)
Этот литая синтаксис вы используете, (one *)dp
является C-стиль, который в этом случае сводится к эквиваленту reinterpret_cast<one*>(bp);
. Было бы лучше использовать reinterpret_cast
, если это то, что вы на самом деле собираетесь делать, если не по какой-либо другой причине, кроме как написать самодокументирующий код.
Если вы действительно хотите получить one*
от two*
, у вас есть два варианта.
- Создать иерархию наследования, так что вы можете бросить, не вызывая UB
- Создать оператор преобразования, так что вы можете построить
one
из two
или наоборот.
В вашем случае, так как вы цикл над массивом one
объектов и пытаетесь выполнить two
метод через эти указатели, лучше всего, вероятно, # 1 выше.
class one
{
public :
virtual void out()
{
cout<<"one ";
}
};
class two : public one
{
public :
void out()
{
cout<<"two ";
}
};
Теперь ваша петля будет работать, и код испустит «два два два» вместо того, что вы видели на самом деле.
Ну, вы солгали компилятору. Почему вы должны ожидать чего-то разумного? –
Это [неопределенное поведение] (http://en.wikipedia.org/wiki/Undefined_behavior), простой и простой. – ildjarn
почему undefined? –