gpt4 book ai didi

c++ - 为什么我的虚拟方法在 C++ 中被跳过?

转载 作者:行者123 更新时间:2023-11-27 23:16:31 25 4
gpt4 key购买 nike

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

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

                                     Entity
Item Creature
Weapon Armor

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

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

问题来了。 Entity 有一个名为 dumpObject() 的虚方法,它打印它拥有的变量的状态。 dumpObject()Item 中也是虚拟的。从 Item 调用时,该方法首先调用 Entity 的转储:

                 Entity::dumpObject();

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

                 Item::dumpObject();

我的问题:

由于 ItemFactory 包含 - WeaponsArmor,并且主程序中的指针指向一个 Item,不应该调用 "itemPointer->dumpObject();" 转储武器/装甲的值(取决于它指向的......),这也会转储 Item 中的值,这也会转储 Entity 中的值?

当我运行代码时,唯一被转储的部分是 Item 和 Entity 中的部分。

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

这是代码片段

我已经包含了 header ,只是尽量减少我发布的代码量


项目.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;
}
}

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;
}

装甲.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();

};

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 中指针的逻辑是错误的?

最佳答案

那么这是你的问题:

Item * pReturnValue = new Item(*pItem);

这为您提供了一个浅表拷贝,这样您就不会获得ArmorWeapon

如果您只需要在给定基类实例的情况下进行复制,请在基类中定义一个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() 协变返回值的使用。 IE。返回值确实不同,但由于方法签名匹配且返回值相互派生,因此调用是虚拟的。

然后你可以写:

Item * pReturnValue = pItem->clone();

参见:Wikipedia原型(prototype)模式的背景。

关于c++ - 为什么我的虚拟方法在 C++ 中被跳过?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15939008/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com