2013-05-29 58 views
0

我有一个相当阻塞的问题,我不明白。一般来说,我正在做一种蚁穴模拟。里面有一条主要通道分成几段,蚂蚁可以从一些段进入室内。所有这三个类(通道,段,分庭)都有一个共同点 - 收集目前正在访问的蚂蚁。因此,有一个抽象类AntHolder,其中包含vector<Ant*>(只有成员相关的情况下被示出):当功能退出时指针设置为空指针

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

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

antEnter功能在派生类不同地实现,但通常用于添加的蚂蚁和ants的目的。从派生类特别是我感兴趣的AntChamber类(这里也不太被省略重要的成员):

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功能,但它增加了Item对象items集合。 (项是例如食品,由蚂蚁移动从一个室到另一个。)下面示出执行两种功能:

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指针,它通过参数传递。我已经尝试在一些simplier代码来模拟这种情况下,如:

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; 
    } 

,但它似乎只是做工精细 - 没有指针的是000000。

+3

你是否检查过'chamber-> antEnter(ant))的返回值;'不是'false'?由于我们没有一个简短的自包含示例,因此很难确定问题:http://www.sscce.org/ –

+0

在antEnter中,itemCapacity和additionalCapacity的值是什么?你真的想在antEnter中使用itemCapacity吗? –

+0

@ Shafik Yaghmour - 我做到了。情况并非如此。当我测试它时,两个矢量都是空的,两个容量都较高 - 例如, 10 + 5。正如你所看到的,我试图简化例子,但是我的尝试失败了:) – Sushi271

回答

1

哦,我的上帝,我是SOOO盲目...

我做SSCCE,为沙菲克Yaghmour建议,我注意到这个问题,在做的。

我用了一个心理跳跃,说chamber->items.back()chamber->ants.back()都是NULL,因为其实他们不是!但是他们在课堂上受到保护,所以我在两个课程中写了一个函数来获得第i个项目/蚂蚁。问题是这个功能。它提出了标准idiotproof防止给索引超出矢量的债券,但犯了一个错误这样做:

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

所以它总是返回0 ...当我寻找这个问题时,我可能会观察这种方法数百次,并且从未发现任何错误(至今)。

愚蠢的错误...非常感谢你Shafik

+0

这是做SSCCE的要点之一,我猜你可能会自己想出来。在很多情况下,试图用较小的例子来演示这个bug会导致找出问题。 –