【问题标题】:base class pointer, accessing derived class member variables?基类指针,访问派生类成员变量?
【发布时间】:2015-02-04 23:40:01
【问题描述】:

我正在削减代码以使其更具可读性,我希望我不会让这变得难以理解。

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 个派生类,所以我需要库存作为指向基类的指针吗?

【问题讨论】:

  • stackoverflow.com/questions/11855018/c-inheritance-downcasting你需要知道什么时候你需要以某种方式投射哪些对象。
  • 我正在研究演员阵容,但我不太确定在这种情况下它会如何工作。是否可以使用铸造指针指向我的库存中的项目?我的意思是,如果库存[1] 是一种武器,我可以使用装箱点指向它以获取访问权限?
  • 是的,但你在施法时需要确保它是武器。

标签: c++ pointers inheritance


【解决方案1】:

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

如果你想使用虚函数,最好在派生类中使用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();
}

【讨论】:

  • 只需使用if (Weapon * weapon_ptr = dynami_cast&lt;Weapon *&gt;(item)) { weapon_ptr-&gt;getAttAcc(); }。与手动添加getItemType 函数相比,它更安全且输入更少。你的另一点是正确的。
  • 在 C++ 中使用 C 风格类型转换是一种糟糕的形式,在处理多态类型时很危险。 \改为使用 C++ 强制转换运算符。在这种情况下,dynamic_cast 是正确的方法。
  • “但是,虚函数需要有相同的参数,其他方式它不算是虚函数。”应该替换为“但是虚函数只能被具有相同签名的函数覆盖。否则,它只是一个重载。“
  • 我尝试使用 5gon12eder 的编码,它在 ')' 之前给了我一个预期的主要表达式。知道为什么吗?是的,我纠正了 dinami 错误编辑:没关系,我想通了......愚蠢的错误
  • 你们太棒了,非常感谢,我想我现在明白了……再次感谢!
【解决方案2】:

您最直接的错误是您声明了 int Weapon::getAttAcc(weapon&),其签名与虚函数 int item::getAttAcc() 不匹配。因为它们不匹配,所以您没有覆盖基类中的函数。

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

也就是说,除非每个项目都可以用于攻击,否则不要将 getAttAcc(我假设它是“获取攻击精度”的缩写)作为 class item 的虚拟函数。

相反,在查看库存时,如果您只想为武器做某事,请使用 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() ...
    }

【讨论】:

    猜你喜欢
    • 2011-01-27
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多