长话短说:我正在研究的程序就像流氓一样 - 尽管这个问题并不是真的需要。
以下是与此问题相关的类的层次结构树:
Entity
Item Creature
Weapon Armor
我在Entity中声明了几个虚函数,它们在从它派生的类中也是虚函数。
我不确定如何说出我的问题,但我会解释问题并在下面发布代码。我有一个工厂类型类,名为 ItemFactory,,它打开一个xml文件并使用我制作的简单解析器 - 并创建Item对象并设置它们的值。它有一个返回 Item 指针的方法。在我的主文件中,我声明/定义了一个 ItemFactory 对象。当需要在游戏中删除项时,我会使用类型为项的指针, 并调用该方法随机选择项指向。所有这一切都很完美..
这是问题所在。 实体有一个名为 dumpObject()的虚方法,它打印出变量的状态。 dumpObject()在项中也是虚拟的。当从项目调用它时,该方法首先使用以下方法调用实体转储:
Entity::dumpObject();
然后它会转储它自己的变量..我对武器和 Armor 做同样的事情,除非使用它:
Item::dumpObject();
由于 ItemFactory 同时包含 - 武器和 Armor ,主程序中的指针指向项目,不应该调用 “itemPointer-> dumpObject();” 转储Weapon / Armor的值(取决于它指向的......)还会将值转储到项中,这也会转储实体中的值?
当我运行代码时,唯一被转储的部分是Item和Entity中的部分。
如果我需要提供更多详细信息,请与我们联系。有什么建议?谢谢!
我包含了标题,只是尽量减少我发布的代码量
Item.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;
}
Entity.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;
}
}
Weapon.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;
}
Armor.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();
Entity.h
#include "XMLSerializable.h"
#include <vector>
class Entity : public XMLSerializable {
public:
Entity(void);
virtual ~Entity(void);
virtual void dumpObject();
virtual void dumpObjectData();
};
Item.h
#include "Entity.h"
class Item : public Entity{
public:
Item(void);
virtual ~Item(void);
virtual void dumpObject();
virtual void dumpObjectData();
};
Weapon.h
#include "Item.h"
class Weapon : public Item {
public:
Weapon(void);
virtual ~Weapon(void);
virtual void dumpObject();
virtual void dumpObjectData();
};
Armor.h
#include "Item.h"
class Armor : public Item {
public:
Armor(void);
virtual ~Armor(void);
virtual void dumpObject();
virtual void dumpObjectData();
};
ItemFactory.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中的指针的逻辑是错误的吗?
答案 0 :(得分:4)
这是你的问题:
Item * pReturnValue = new Item(*pItem);
这会为您提供浅层副本,以便您不会获得Armor
或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();
有关Prototype模式的背景信息,请参阅:Wikipedia。