указатели — Почему мой виртуальный метод пропускается в C ++?

Короче говоря: программа, над которой я работаю, похожа на мошенника, хотя в этом вопросе она и не нужна.

Вот дерево иерархии для моих классов, связанных с этим вопросом:

                                     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 неверна?

0

Решение

Ну вот твоя проблема:

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();

Увидеть: Википедия для фона на шаблоне прототипа.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]