2014-07-24 3 views
3

일부 배경 :개체의 변수가 벡터에서 재설정 됨 (void *에서 캐스팅)

나는 만들고있는 게임에서 Box2D를 사용하고 있습니다. Box2D 객체에 "사용자 데이터"를 저장하는 방법이 있습니다. 이 "사용자 데이터"는 void *를 사용하므로 사용자 정의 데이터를 저장하는 데 사용할 수 있습니다. 이제 Box2D 충돌이 발생하면이 "사용자 데이터"를 사용하여 충돌 한 객체를 식별 할 수 있습니다. 그런 다음 데이터를 클래스로 캐스팅하고 해당 클래스의 함수 나 변수에 액세스 할 수 있습니다 (해당 인스턴스에 대한 참조로 "사용자 데이터"를 설정 한 경우 해당 클래스의 특정 인스턴스). 두 세트의 "사용자 데이터"가 있습니다. 하나는 클래스 인스턴스에 대한 참조이고 다른 하나는 구조체에 대한 참조이므로 객체 유형을 확인할 수 있습니다.

이것은 벡터에없는 개체에 적합합니다.이 테스트를 거쳤으며 재설정하지 않고 클래스 인스턴스의 함수 및 변수에 액세스하고 수정할 수 있습니다. 하지만 std :: vector < Tile> void *에서 캐스팅하여 객체에 액세스하면 수정 한 변수가 즉시 재설정됩니다.

관련 코드 :

내가 이런 식으로 "사용자 데이터"로 설정 :

tile->SetUserData(static_cast<Entity*>(this)); 
ball->SetUserData(static_cast<Entity*>(this)); 

bUserData* bud = new bUserData; 
bud->entityType = BALL; 
ballFixture.userData = bud; 

bUserData* bud = new bUserData; 
bud->entityType = TILE; 
tileFixture.userData = bud; 

MyContactListener 클래스는 충돌이 시작 및 종료 시점을 추적 유지를,이 어디에서 주조도 void * ~ foo *가 발생합니다.

MyContactListener.cpp 

std::vector<Tile> solidTiles; 
Ball ball; 

// Called when two objects begin to touch. 
void MyContactListener::BeginContact(b2Contact* contact) { 

    // Cast from void* to a struct, from which I can check the object type. 
    bUserData* budA = (bUserData*)contact->GetFixtureA()->GetUserData(); 
    bUserData* budB = (bUserData*)contact->GetFixtureB()->GetUserData(); 

    // Cast from void* UserData to Entity* (super-class of all the entities). 
    Entity* entityA = (Entity*)contact->GetFixtureA()->GetBody()->GetUserData(); 
    Entity* entityB = (Entity*)contact->GetFixtureB()->GetBody()->GetUserData(); 

    if((budA->entityType == TILE && budB->entityType == BALL)) { 
     Tile* tile = (Tile*)entityA; // Tiles are in std::vector<Tile> 
     Ball* ball = (Ball*)entityB; // Only one ball instance exists 

     // Modifying a tile instance variable, gets reset to the original value immediately! 
     tile->flaggedToErase = true; 
     // This works fine! 
     ball->setColorToBlue = true; 
    } 
} 

질문 : 변수를 어떻게 유지합니까? 벡터의 타일 인스턴스가 원래 값으로 재설정되지 않습니까?

+1

이 재설정되었거나 전혀 변경되지 않았습니까? –

+0

사용자 데이터 포인터를'Tile *'으로 설정할 때'Entity * '에 대한 명시 적 캐스트를 수행하고 있습니까? 그렇지 않으면'Entity *'캐스트가 정의되지 않은 행동이다. 'Tile * '에서'Entity * '로 형변환 한 다음 암시적인'void *'캐스트를 사용하면'void *'에서'Entity *'로 캐스트하면됩니다. – Simple

+0

Tugrul : 타일을 변경 한 후에 타일의 변수를 인쇄 해 보았습니다. tile-> flaggedToErase가 true라는 것을 보여줍니다. – lefti

답변

1

Tile 또는 Tile*의 벡터로 생각 되나요? 짐작할 수 있듯이이 문제는 객체의 포인터를 저장하는 vector<Tile*>과 반대로 객체의 복사본을 저장하는 vector<Tile>을 사용하는 것으로 의심됩니다. 이와 함께 ...

std::vector<Tile> tiles; 

Tile t; 
t.foo = 123; 
tiles.push_back(t); // a copy of t is put into the vector 

t.foo = 456; // changes t, but not the copy in the vector 

Tile t2 = tiles[0]; // makes yet another copy (t2.foo == 123) 
:

이 비교

std::vector< Tile* > tiles; 

Tile* t = new Tile; 
t->foo = 123; 
tiles.push_back(t); // a pointer is put into the vector 

t->foo = 456; // also changes in the vector because it's the same thing 

Tile* t2 = tiles[0]; // still the same thing (t2->foo == 456) 

당신은 객체 (안 포인터)의 벡터를 가지고 벡터 내부를 변경하려는 경우, 당신은 할 수있다 그것은 다음과 같습니다 :

std::vector<Tile> tiles; 
Tile& t = tiles[0]; // note the ampersand, accesses by reference 
t.foo = 456; // changes inside the vector 

// I think you can also do this 
tiles[0].foo = 456; 

그러나이 작업을 수행하려면 벡터 자체를 사용할 수 있어야합니다. 어떤 위치에 변경하고자하는 요소가 있는지. 귀하의 경우, 요소가 벡터 내에서 어떤 위치에 있는지 알지 못하므로 vector<Tile*>을 사용하는 것이 가장 간단한 솔루션입니다.

관련 문제