从向量中删除对象会破坏C ++中的另一个对象

时间:2011-08-04 19:24:18

标签: c++ object vector

在过去的几天里,我一直在编写一个系统,以便于编写基于文本的冒险(类似于Colossal Cave或Zork)。我一直遇到Item子系统的问题。

有关的三个课程是房间,门和项目。

当我从Room的项目向量中移除Item对象时,同一房间的Door向量中的最后一个Door对象已损坏。应该注意的是,所有Door和Item对象都是通过引用传递的,这允许人们编写自己的Door和Item子类,并且仍然将它们与系统一起使用。奇怪的是,门对象的唯一属性是“位置”属性,该属性告诉玩家门在房间的哪个位置。所有其他属性保持不变,这告诉我门对象的指针尚未移动,但它指向的数据已被更改。

这会导致玩家看到门描述的错误。为了测试,我没有给门特别说明,它们有太多,所以他们使用我的内部,罐头描述。

You are in a large parlour room.  It is obviously that of a very wealthy man.
Adorning the walls are many dusty heads of big game.
There is a door in the direction of West.
There is a door in the direction of East.
There is a door in the direction of North.
Hanging on the wall, you see a really bad ass looking sword.
Parlour] pickup sword
Picked up the Sword of the Gods
You pick up the sword.
In doing so, you feel very powerful.
There is a door in the direction of West.
There is a door in the direction of East.
There is a door in the direction of ?.
Parlour] 

玩家仍然可以从一个房间移动到另一个房间,因此门对象中的其余数据看似没问题。但是,存储“Location”属性的std :: string已更改。在代码中没有任何地方可以更改该属性。

有人能看出为什么会这样吗?我的代码或对象处理中是否有明显的错误?因为我无法确定发生了哪个文件,所以需要发布大量代码。

您可以在此处下载我的所有代码的zip文件:http://www.filedropper.com/advsys

这是我的代码,这肯定不是全部,因为我有超过9个文件的467行 当你试图拿起剑时,就会调用它。

void OnPickup() {
    std::cout << "You pick up the sword." << std::endl;
    std::cout << "In doing so, you feel very powerful." << std::endl;

    int itemNum = ParentRoom->HasItem(Name);
    if (itemNum != -1) {
        // Wait, the item ISN'T in the room?  Then how the hell did we get HERE?
        // Whatever, error out.
        std::cout << "For some strange reason, you were hallucinating about the " + Name + "." << std::endl;
    } else {
        PlayerRef->Inventory.push_back(new GodSword(ParentRoom, PlayerRef));
        ParentRoom->RemoveItem(itemNum);  // Corrupts a door
        //delete ParentRoom->Items[itemNum];  // SEGFAULT
    }
}

门和物品是这样分配的。 新的Door实例传递给文本位置,它在房间内的位置,以及指向目标的指针。项目被传递给他们所在房间的引用,以及对玩家的引用。

house["parlour"].Doors.push_back(new Door("North", 'N', &house["bedroom"]));
house["parlour"].Items.push_back(new GodSword(&house["parlour"], &player));

项目会像这样从房间中删除。打印门列表以进行调试。

void Room::RemoveItem(int item) {
    Items.erase(Items.begin() + item);

     for (int i = 0; i < Doors.size(); i++) {
         std::cout << Doors[i]->GetDescription() << std::endl;
     }
}

房间声明如下。

class Room {
    public:
        std::vector<Door *> Doors;
        std::vector<Item *> Items;

        std::string LongDescription;
        std::string ShortDescription;
        std::string Name;

        bool DescribeDoors;
        bool DescribeItems;
        bool BeenHere;

        Room();
        ~Room();

        int HasDoor(char dir);
        int HasItem(std::string name);
        void OutputDescription(bool forceLong=false);
        void RemoveItem(int item);
};

我想不出我需要添加的任何其他内容。如果您需要查看另一个文件,或者如何声明其他类,等等......上面有一个zip链接。

2 个答案:

答案 0 :(得分:3)

在您发布的代码中:

   int itemNum = ParentRoom->HasItem(Name);
    if (itemNum != -1) {
        // Wait, the item ISN'T in the room?  Then how the hell did we get HERE?
        // Whatever, error out.
        std::cout << "For some strange reason, you were hallucinating about the " + Name + "." << std::endl;
    } else {
        PlayerRef->Inventory.push_back(new GodSword(ParentRoom, PlayerRef));
        ParentRoom->RemoveItem(itemNum);  // Corrupts a door
        //delete ParentRoom->Items[itemNum];  // SEGFAULT
    }
当您尝试删除它时, itemNum将为-1,这可能会导致您注意到的段错误/内存损坏。测试的意义是否与应该是什么相反?

答案 1 :(得分:0)

Dewtell发现导致内存损坏的错误。但是,代码中的真正错误在于这一行:

int itemNum = ParentRoom->HasItem(Name);

应该是:

int itemNum = ParentRoom->HasItem(PickupName);

否则永远无法找到匹配。