基类指针,访问派生的类成员变量

base class pointer, accessing derived class member variables?

本文关键字:成员 变量 派生 指针 访问 基类      更新时间:2023-10-16

im 剪切代码以使其更具可读性 我希望我不会让这变得难以理解。

class player : public character{
public:
    // ---------stuff-------
protected:
    // ------stuff--------
    vector <item*> inventory;
};
class item {
public:
    // -----stuff------------
    virtual float getHealth(){};
    virtual int getDef(){return 0;};
    virtual int getAttAcc(){return 0;};
    virtual int getAttPow(){return 0;};
    virtual ~item();
protected:
    string name;
    string type;
    int value;
    int weight;
};
class weapon : public item{
public:
    weapon(int attPow, int attAcc, int inValue, int inWeight, string inType, string inName);
    weapon(const weapon& cWeapon);
    int getAttAcc(weapon& weapon){return attAcc;};
    int getAttPow(){return attPow;};
    ~weapon(){};
protected:
    int attAcc;
    int attPow;
};

当我需要武器(用指针存储在库存中)来访问其 attAcc 和 attPow 时,我的问题就来了。
我尝试过的事情:我尝试添加虚拟函数,然后使用派生类更改它们。

我尝试将其排除在基类之外,但由于库存是指向项目的指针向量,因此不允许这样做。

最初我希望玩家有 2 个用于武器和盔甲的指针,但因为库存是一个不起作用的物品指针。

我省

略了其他项目的课程,因为我确定一旦我弄清楚了其中一个,其他项目是相同的。 由于我有 3 个派生类,我需要库存来指向基类,对吗?

不确定,你想在这里做什么。

如果你想使用虚函数,最好在派生类中使用 virtual 关键字。

但是,虚函数

必须具有相同的参数(又名签名),否则它只会重载基类函数,虚函数机制将不起作用。

在你的例子中,函数int weapon::getAttAcc(weapon& weapon)不会覆盖基类int item::getAttAcc(),因为初始函数没有参数。

你可以添加一个参数到 int item::getAttAcc(weapon& weapon),如果这是你想要的。

另一种解决方案是添加一个类型函数:

class Item {
   public:
     virtual int getItemType() = 0; // this will make function pure virtual
};
class Weapon : public Item {
   public:
     virtual int getItemType() { return 1; }
     int getAttAcc() {return attAcc;}
}
Item * item = // something
if (item.getItemType() == 1) // weapon
{
   Weapon * weapon = (Weapon)item;
   weapon->getAttAcc();
}

或者,正如其他评论员所建议的那样。 更C++的方式:

// cast will be successful only for Weapon type object.
if (Weapon * weapon = dynamic_cast<Weapon *>(item)) { // weapon
    weapon->getAttAcc();
}

你最直接的错误是你声明了 int weapon::getAttAcc(weapon&),其签名与虚函数 int item::getAttAcc() 不匹配。由于它们不匹配,因此尚未重写基类中的函数。

更根本的是,类项声明仅对类武器有意义的函数是没有意义的。(当然,除非它们是有意义的。盔甲类型的物品是否也有 attPow 和 attAcc?

也就是说,不要让getAttAcc(我认为它是"获取攻击准确性"的缩写)成为类项的虚拟函数,除非每个都可用于攻击。

相反,在查看库存时,如果您只想为武器做一些事情,请使用dynamic_cast检查类型。例如:

class weapon : public item {
public:
    int getAttAcc() { return attAcc; };
    ...
}

item *anItem = ...;
if (weapon* aWeapon = dynamic_cast<weapon*> (anItem)) {
    ... do something with aWeapon->getAttAcc() ...
    ... and/or with aWeapon->getAttPow() ...
    }