Короче говоря: программа, над которой я работаю, похожа на мошенника, хотя в этом вопросе она и не нужна.
Вот дерево иерархии для моих классов, связанных с этим вопросом:
Entity
Item Creature
Weapon Armor
У меня есть несколько виртуальных функций, объявленных в Entity, которые также являются виртуальными в классах, производных от него.
Я не уверен, как сформулировать свой вопрос, но я объясню проблему и опубликую код ниже. у меня есть завод тип класса, называется ItemFactory, он открывает файл XML и использует созданный мной простой синтаксический анализатор, а также создает объекты Item и устанавливает их значения. У него есть метод, который возвращает Вещь указатель. В моем основном файле я объявляю / определяю ItemFactory объект. Когда Вещь нужно удалить в игре, я использую указатель, который имеет тип, Вещь,
и вызвать метод, чтобы случайно выбрать Вещь указать на. Все это прекрасно работает ..
Здесь проблема. сущность имеет виртуальный метод под названием dumpObject () который печатает состояние переменных, которые он имеет. dumpObject () также виртуален в Вещь. Когда он вызывается из Вещь, метод сначала вызывает субъекта дамп с этим:
Entity::dumpObject();
Затем он сбрасывает свои собственные переменные .. Я делаю то же самое для Оружие а также броневой кроме использования этого:
Item::dumpObject();
Так как ItemFactory держит оба — оружие а также броневой, и указатель в основной программе указывает на Вещь, не должен звонить «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. Lol Я предполагаю, что моя логика для указателя в Main неверна?
Ну вот твоя проблема:
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();
Увидеть: Википедия для фона на шаблоне прототипа.
Других решений пока нет …