2013-05-29 3 views
0

저는 이해가 안되는 문제가 꽤 있습니다. 일반적으로 나는 매끄러운 시뮬레이션을 만들고 있습니다. 개미로 나뉘어져있는 구역과 개미로 들어갈 수있는 구역이 있습니다. 이 세 클래스 (항로, 세그먼트, 상공 회의소)는 공통점이 있습니다 - 현재 그들을 방문하는 개미 수집. 그래서 vector<Ant*> (경우와 관련이 도시되어 멤버 만)를 포함하는 추상 클래스 AntHolder 존재이다포인터가 함수 밖으로 나가면 포인터가 널 포인터로 설정됩니다.

class AntHolder 
    { 
    protected: 
     std::vector<Ant*> ants; 
     /* some other members here */ 

    public:   
     virtual bool antEnter(Ant* ant) = 0; 
     /* some other functions here */ 
    }; 

antEnter 함수 파생 ​​클래스 다르게 구현되지만 일반적 ants 개미 추가의 목적을 제공한다 .

class AntChamber : public AntHolder 
    { 
    protected: 
     int itemCapacity; 
     int additionalCapacity; 
     std::vector<Item*> items; 

     bool hasFood; 
     bool hasEgg; 

    public: 
     bool putItem(Item* item); 
     virtual bool antEnter(Ant* ant); 
    }; 

putItem 기능은 antEnter 기능과 유사하지만 items 컬렉션에 Item 객체를 추가합니다 : 파생 클래스 특히 내가 AntChamber 클래스의 관심에서 (여기 또한 덜 중요한 회원은 생략했다). (항목은 또 다른 하나의 챔버에서 개미로 이동, 예를 들어 음식이다.) 다음은 두 기능의 구현이 도시되어있다 :

bool AntChamber::antEnter(Ant* ant) 
    { 
     if (items.size() + ants.size() == itemCapacity + additionalCapacity) return false; 

     ants.push_back(ant); 
     return true; 
    } 

    bool AntChamber::putItem(Item* item) 
    { 
     if (items.size() == itemCapacity || 
      items.size() + ants.size() == itemCapacity + additionalCapacity) 
      return false; 

     if (item->getItemKind() == Food) hasFood = true; // Food == enum value 
     else if (item->getItemKind() == Egg) hasEgg = true; // Egg == enum value 

     items.push_back(item); 
     return true; 
    } 

당신은 그들이 거의 동일 이니까, 분명히 알 수 있습니다. 그러나 그 효과에 관해서, 결정적이며 놀라운 차이가 있으며, 그것이 내 문제의 핵심입니다.

이미 내가 AntChamber* chamber을 생성했다고 가정 해 보겠습니다. 내가 다음 코드 조각을 실행하면 :

Item* item = new Item(Food); 
    chamber->putItem(item); 

,이 오브젝트와 일부 메모리에 그 itemchamber->items.back() 점 모두 후. 나는 코드의 유사 부분을 실행할 때 :

Ant* ant = new Ant(chamber); 
    chamber->antEnter(ant)); 

, 그 객체에 ant 점,하지만 chamber->ants.back() 점 후 NULL로!

실제로 무엇이 진행되고 있는지 이해할 수 없습니다. 특히 putItemantEnter은 사실 동일한 작업을 수행합니다. push_back 포인터가 매개 변수로 전달되었습니다. 이미 같은 몇 가지 더 간단 코드에서 이러한 경우를 시뮬레이션하기 위해 노력했다 :

class A { }; 
    class B { }; 

    class C 
    { 
     vector<A*> va; 
     vector<B*> vb; 
    public: 
     A* vaBack() { return va.back(); } 
     B* vbBack() { return vb.back(); } 

     void addA(A* a) { va.push_back(a); }   
     void addB(B* b) { vb.push_back(b); } 
    }; 

    int main(int argc, char** argv) 
    { 
     A* a = new A(); 
     B* b = new B(); 
     C* c = new C(); 

     cout << (unsigned int)a << endl; 
     c->addA(a); 
     cout << (unsigned int)c->vaBack() << endl; 

     cout << (unsigned int)b << endl; 
     c->addB(b); 
     cout << (unsigned int)c->vbBack() << endl; 

     delete c; 
     delete b; 
     delete a; 
    } 

하지만 잘 작동 보인다 - 포인터 아무도 0x000000에서입니다.

+3

'chamber-> antEnter (ant))의 반환 값을 확인 했습니까? '가 아닌'false'입니까? Short, self contained 예제가 없으므로 문제를 해결하기가 어렵습니다. http://www.sscce.org/ –

+0

antEnter에서 itemCapacity 및 additionalCapacity의 값은 무엇입니까? antEnter에서 itemCapacity를 사용하고 싶습니까? –

+0

@Shafik Yaghmour - 그랬어. 그것은 사실이 아닙니다. 테스트 할 때 두 벡터가 모두 비어 있습니다. 두 가지 용량이 모두 높습니다. 보시다시피 예를 단순화하려고 시도했지만 시도가 실패했습니다. :) – Sushi271

답변

1

오 나의 하나님, 내가

나는 조언 Shafik Yaghmour로, SSCCE을했고, 그 일을하는 동안 문제를 발견 ... sooo를 장님입니다.

실제로 나는 그렇지 않았기 때문에 chamber->items.back() 또는 chamber->ants.back()이 NULL이라는 정신적 도약을 사용했습니다! 하지만 그들은 클래스에서 보호되어 있으므로 두 클래스 모두에서 i 번째 항목/개미에 도달하는 함수를 작성했습니다. 문제는이 기능이었다. 이 벡터의 채권에서 인덱스를 제공에 대한 표준 idiotproof 보호를 만들었지 만, 그렇게 실수를 :

if (idx < 0 || ants.size() >= idx) return 0; // SHOULD BE <= !!! 
    return ants[idx]; 

그래서 항상 0을 반환 ...그리고이 문제를 찾을 때 아마도이 방법을 수백 번 보았을 것이고, 지금까지는 아무 것도 발견하지 못했을 것입니다.

어리석은 실수 ... 감사합니다. 매우 샤프트.

+0

그건 SSCCE를하는 지점 중 하나이며, 나는 당신이 스스로 알아낼지도 모른다고 생각했습니다. 대부분의 경우 작은 예제에서 버그를 보여 주려고하면 문제를 파악하게됩니다. –

관련 문제