重载基类和派生类中的运算符

时间:2018-06-20 05:30:54

标签: c++

我有一个基础类Item和一个派生类Weapon&Shield。都重载<<。

// item(base) operator overload
ostream& operator<<(ostream& os, const Item& a_item)
{
    os << "     Item Object - " << endl;
    os << "          Name: " << a_item.m_name << endl;
    os << "          Cost: " << a_item.m_cost << endl;
    os << "          Purpose: " << a_item.m_purpose << endl;

    return os;
}

并且:

// weapon(derived) operator overload
ostream & operator<<(ostream & os, const Weapon & a_weapon)
{
    os << "Weapon - " << endl;
    os << "     Name: " << a_weapon.m_name << endl;
    os << "     Cost: " << a_weapon.m_cost << endl;
    os << "     Purpose: " << a_weapon.m_purpose << endl;

    return os;
}

// shield(derived) operator overload
ostream & operator<<(ostream & os, const Shield & a_shield)
{
    os << "Shield - " << endl;
    os << "     Name: " << a_shield.m_name << endl;
    os << "     Cost: " << a_shield.m_cost << endl;
    os << "     Purpose: " << a_shield.m_purpose << endl;

    return os;
}

现在,我有一个vector<Item> inventory,在其中添加了武器和盾牌。当我遍历库存并列出项目时,我得到了Item运算符,而不是那个特定项目的那个。这是我叫喊的方式:

// person(derived) operator overload
ostream& operator<<(ostream& os, const Person& a_person)
{
    os << "Person Object - " << endl;
    os << "     Name: " << a_person.m_name << endl;
    os << "     Level: " << a_person.m_level << endl;
    os << "     Hit Points: " << a_person.m_hit_points << endl;
    os << "     Inventory: " << endl;

    for (auto i = 0; i < a_person.m_inventory.size(); i++)
    {
        os << "     " << a_person.m_inventory[i] << endl;
    }

    return os;
}

enter image description here

我的问题是为什么它调用基数的运算符重载,而不是派生的?可以告诉它从派生类中调用它吗?

2 个答案:

答案 0 :(得分:5)

除了object slicing problem之外,您的代码还遇到另一个概念性问题。当您引用基类时,您期望在运行时调用派生类型的operator<<函数是没有根据的。因为函数不是多态的,所以这行不通。

您必须稍微改变策略以使其像多态函数一样工作。

  1. 仅对基类实施operator<<函数。
  2. 拥有virtual个成员函数来完成实际工作。
  3. virtual函数调用operator<<成员函数。

说明代码:

struct Base
{
   virtual std::ostream& print(std::ostream& os) const
   {
      // Print base class details

      return os;
   }
};

struct Derived : Base
{
   virtual std::ostream& print(std::ostream& os) const
   {
      // Do the base class printing first
      Base::print(os);

      // Print the derived class details.

      return os;
   }
};

std::ostream& operator<<(std::ostream& os, Base const& b)
{
   // This will be a polymorphic call.
   return b.print(os);
}

答案 1 :(得分:2)

std::vector将其元素保留在自己的私有数组中,因此它们按值存储。类型Item的值始终将Item作为其最派生的类,因此,当您在其中存储Weapon时,向量中保留的只是一个ItemItem-Weapon的一部分),并且在打印时只能报告为Item