0

长话短说:我正在研究的程序是一个流氓,尽管这个问题并不真正需要。

这是与此问题相关的类的层次结构树:

                                     Entity
                        Item                     Creature
                  Weapon     Armor     

我在 Entity 中声明了几个虚函数,它们在从它派生的类中也是虚函数。

我不确定如何表达我的问题,但我会解释问题并在下面发布代码。我有一个名为ItemFactory的工厂类型类,它打开一个 xml 文件并使用我制作的简单解析器 - 并创建 Item 对象并设置它们的值。它有一个返回Item指针的方法。在我的主文件中,我声明/定义了一个ItemFactory对象。当需要在游戏中放置一个Item时,我使用一个指针,即Item类型,并调用该方法随机选择一个Item指向。所有这一切都完美无缺..

这就是问题所在。实体有一个名为dumpObject()的虚拟方法,它打印它所拥有的变量的状态。dumpObject()在Item中也是虚拟的。当从Item调用它时,该方法首先使用以下方法调用Entity 的转储:

                 Entity::dumpObject();

然后它转储它自己的变量。我对武器盔甲做同样的事情,除了使用这个:

                 Item::dumpObject();

我的问题:

由于ItemFactory同时拥有 - WeaponsArmor,并且主程序中的指针指向一个Item,因此不应调用“itemPointer->dumpObject();” 转储 Weapon/Armor 的值(取决于它指向的..),这也会转储Item中的值,这也会转储Entity中的值?

当我运行代码时,唯一被转储的部分是项目和实体中的部分。

如果我需要提供更多详细信息,请告诉我。有什么建议么?谢谢!

这是代码片段

我包含了标题,只是试图尽量减少我发布的代码量


项目.cpp

void Item::dumpObject(){
    cout << "Item:" << endl;
    dumpObjectData();
}

void Item::dumpObjectData(){
    Entity::dumpObjectData();
    cout << "        [Weight] " << getWeight() << endl;
    cout << "         [Value] " << getValue() << endl;
    cout << "      [Quantity] " << getQuantity() << endl;
    cout << "   [Enchantment] " << getEnchantment() << endl;
}

实体.cpp

void Entity::dumpObject(){
    cout << "Entity:" << endl;
    dumpObjectData();
}

void Entity::dumpObjectData(){
    XMLSerializable::dumpObjectData(); //XMLSerialization handles parsing

    cout << "          [Name] " << getName() << endl;
    cout << "   [DisplayChar] " << getDisplayChar() << endl;
    cout << "    [Properties] " << endl;

    for( auto it = m_vProperties.begin(); it != m_vProperties.end();it++ ){
            cout << "       - " << (*it) << endl;
    }
}

武器.cpp

void Weapon::dumpObject(){
    cout << "Weapon:" << endl;
    dumpObjectData();
}

void Weapon::dumpObjectData(){
    Item::dumpObjectData();

    cout << "        [Damage] " << getDamage() << endl;
    cout << "         [Range] " << getRange() << endl;
    cout << "      [Accuracy] " << getAccuracy() << endl;
    cout << "      [AmmoType] " << getAmmoType() << endl;
    cout << "          [Type] " << getType() << endl;
}

装甲.cpp

void Armor::dumpObject(){
    cout << "Armor:" << endl;
    dumpObjectData();
}

void Armor::dumpObjectData(){
    cout << "calls to dump item data"<<endl;
    Item::dumpObjectData();
    cout << "calls to dump armor"<<endl;
    cout << "          [Type] " << getType() << endl;
    cout << "          [Slot] " << getSlot() << endl;
    cout << "    [ArmorValue] " << getArmorValue() << endl;

}

主要的

    ItemFactory myItems = ItemFactory::instance();
    Item * pItem1 = myItems.generateItem();
    pItem1->dumpObject();



标头

实体.h

#include "XMLSerializable.h"
#include <vector>

class Entity : public XMLSerializable {

public:
    Entity(void);
    virtual ~Entity(void);

    virtual void dumpObject();
    virtual void dumpObjectData();

};

项目.h

#include "Entity.h"

class Item : public Entity{

public:
    Item(void);
    virtual ~Item(void);

    virtual void dumpObject();
    virtual void dumpObjectData();

};


武器.h

#include "Item.h"

class Weapon : public Item {
public:
    Weapon(void);
    virtual ~Weapon(void);

    virtual void dumpObject();
    virtual void dumpObjectData();
   
};

盔甲.h

#include "Item.h"

class Armor : public Item {
public:
    Armor(void);
    virtual ~Armor(void);

    virtual void dumpObject();
    virtual void dumpObjectData();

};

项目工厂.cpp

ItemFactory & ItemFactory::instance(){
    static ItemFactory myObj;
    return myObj;
}

ItemFactory::ItemFactory(){
    m_mtRandom.seed( time(NULL) );
    fstream xmlFile;
    xmlFile.open("items.xml");
    vector<XMLSerializable*> pObjects;
    parseXML(xmlFile, pObjects);

    XMLSerializable * pObject;

    for(auto it = pObjects.begin(); it != pObjects.end(); it++){
            pObject = (*it);
            Item * pItem = dynamic_cast<Item*>(pObject);
            if (pItem != NULL){
                    m_vItems.push_back(pItem);
            }
    }
}


ItemFactory::~ItemFactory(){

}


Item * ItemFactory::generateItem() {
    vector<Item*> tempItems;

    for(auto it = m_vItems.begin(); it != m_vItems.end(); it++){
            tempItems.push_back((*it));
    }

    int randomItem = (m_mtRandom() % (m_vItems.size() - 1));


    Item * pItem = tempItems.at(randomItem);

    Item * pReturnValue = new Item(*pItem);

    return pReturnValue;
}

既然我刚刚完成了所有这些工作,我认为除了 Main 之外的任何代码都是必要的。哈哈,我猜 Main 中指针的逻辑是错误的?

4

1 回答 1

4

那么这是你的问题:

Item * pReturnValue = new Item(*pItem);

这是给你一个浅拷贝,这样你就不会得到Armoror Weapon

如果您只需要在给定基类实例的情况下进行复制,请在基类中定义一个clone方法。

看起来您正在尝试使用该prototype模式,所以您确实想创建新实例?

class Entity : public XMLSerializable {

public:
    Entity(void);
    virtual ~Entity(void);

    virtual Entity* clone() const { return new Entity(*this);}

    virtual void dumpObject();
    virtual void dumpObjectData();

};

class Armor : public Item {
public:
    Armor(void);
    virtual ~Armor(void);
    virtual Armor* clone() const { return new Armor (*this);}
    virtual void dumpObject();
    virtual void dumpObjectData();

};

注意协变返回值的使用clone()。即返回值确实不同,但由于方法签名匹配并且返回值是相互派生的,因此调用是虚拟的。

然后你可以写:

Item * pReturnValue = pItem->clone();

有关原型模式的背景信息,请参见:维基百科

于 2013-04-11T01:25:13.770 回答