2013-05-15 4 views
1

У меня есть классы Sphere и Triangle, которые являются подклассами Intersectable. Intersectable имеет публичный переменный член colour. Рассмотрим следующий фрагмент кода:C++ Почему значения одной и той же переменной отличаются?

float t_min = 100000.0f; 
pair<float, f3Vector> point_hit; 
Intersectable * object_hit; 
Triangle triangle; 
Sphere sphere_trans; 
bool hit = false; 

//loop through triangles 
for(unsigned int i = 0; i < mesh->tvi.size(); i++){ 
    ... 

    triangle = Triangle((fRGB)mesh->color[mesh->tci[i].c0], va.toVector3(), vb.toVector3(), vc.toVector3()); 
    point_hit = triangle.intersect(orig, dir, c_near, c_far); 

    if(point_hit.first != 0.0f && point_hit.first < t_min){ 
     object_hit = &triangle; 
     std::cout << "color1 " << object_hit->color << std::endl; 
hit = true; 
     ... 
    } 
} 

// loop through spheres 
for(unsigned int j = 0; j < spheres.size(); j++){ 
    ... 

    sphere_trans = Sphere(sphere.color, center3, sphere.getRadius()); 
    point_hit = sphere_trans.intersect(orig, dir, c_near, c_far); 

    if(point_hit.first != 0 && point_hit.first < t_min){ 
     object_hit = &sphere_trans; 
     std::cout << "color1 " << object_hit->color << std::endl; 
hit = true; 
     ... 
    } 
} 

if(hit){ 
    std::cout << "color2 " << object_hit->color << std::endl; 
} 

Я ожидал, что у меня есть, если выход из видов color1 (1 0 0) и следующий вывод имеет значение с color2 (...) в outprinted цвета должны быть одинаковыми. Однако этого не происходит. Фактически, я всегда получаю тот же результат для color2 (...). Можете ли вы сказать мне, что я делаю неправильно? Благодаря!

+3

Это присваивание 'object_hit' локальному (для цикла for) здесь' object_hit = & sphere_trans; 'поэтому использование' object_hit' после выхода из области действия является неопределенным поведением. –

+0

@ShafikYaghmour Я отредактировал код, чтобы больше не создавать локальную переменную. Но у меня все еще такое же поведение. – kaufmanu

ответ

2

Давайте стройный, что немного вниз ...

Intersectable * object_hit; 
Sphere sphere_trans; 

// loop through spheres 
for(unsigned int j = 0; j < spheres.size(); j++) 
{ 
    ... 
    sphere_trans = Sphere(sphere.color, center3, sphere.getRadius()); 

    if(some condition) 
    { 
     object_hit = &sphere_trans; 
     ...  
    } 
} 

Теперь, когда условие выполнено, то object_hit указывает на sphere_trans. Но в следующий раз по циклу sphere_trans назначен новый объект. Итак, конечно, object_hit также теперь указывает на новый объект, который, вероятно, не тот, который вы хотели.

Лучшим может быть создание object_hit объекта, а не указателя. Или просто удерживайте указатель в массиве.

+0

К сожалению, я не могу позволить 'object_hit' быть объектом (или, по крайней мере, не знаю, как), потому что' Intersectable' является абстрактным типом. Я не понял, что вы имели в виду: «удерживайте указатель в массиве». – kaufmanu

+0

Intersectable является полиморфным, но ваши объекты «Треугольник» и «Сфера» фактически не существуют в какой-либо постоянной форме. Лучше всего скопировать их в object_hit: 'object_hit = new Sphere (sphere_trans);' Все обычные предупреждения об утечке памяти и использовании интеллектуальных указателей применяются ... – Roddy

+0

+1 (На самом деле через два часа с тех пор, как я ударил меня голосовой колпачок) Мне нужно больше спать, я полностью пропустил вторую часть проблемы. –

2

В этом заявлении:

object_hit = &sphere_trans; 

вы назначаете object_hit на адрес локальной (в течение цикла) переменной. Как только вы покидаете петлю for, это pointer более недействительно и разыменование pointer является неопределенным поведением.

+0

Спасибо! Поэтому я добавил объявление «Треугольник треугольника» и «Сфера сфер_транс» в выражения перед циклом for. Но у меня все еще такое же поведение ... – kaufmanu

+0

Я отредактировал сообщение соответственно – kaufmanu

+0

@StringerBell. Вы можете создать небольшую программу, воспроизводящую поведение и, возможно, более конкретно уточнить, какое поведение вы ожидаете. Я не буду смотреть на это снова какое-то время, но, возможно, кто-то еще сможет найти другие проблемы, которые могут существовать. Также в целом, если вы собираетесь делать обновления по своему вопросу, вы должны оставить исходный текст как есть и добавить какие-либо изменения или обновления в конце, иначе новые читатели будут смущены. –

Смежные вопросы