【问题标题】:ostream operator overloading - inheritanceostream 运算符重载 - 继承
【发布时间】:2011-12-04 06:24:55
【问题描述】:

我有一个名为 Item 的基类:

#ifndef ITEM_H
#define ITEM_H

#include <ostream>

class Item {
public:
    virtual ~Item() {}
    virtual void print(std::ostream& out) const {}
    friend std::ostream& operator << (std::ostream& out, Item& item){
    item.print(out);
    return out;
    }
};



#endif

我有一个派生类Tower

#ifndef TOWER_H
#define TOWER_H

#include <iostream>
#include <iostream>
#include <exception>
#include "item.h"
#include "Card.h"

class Tower : public Item {
    unsigned height;
        void print(std::ostream& o) const;
public:
    Tower(const Card& card);
    int demolish(Card& card) const;
    unsigned getHeight() const;
};

#endif

塔的源代码

#include "tower.h"



Tower::Tower(const Card& card){
    height = card.getDis();
}

void Tower::print(std::ostream& o) const {
    o << height;
}


int Tower::demolish(Card& card) const{
    try {
    if(height != card.getDis()){
            throw std::exception ();
        } else {
            return height;
        }
    } catch (std::exception e){
        cout<< "Card's value not enough to demolish the tower." << endl;
    }
}

unsigned Tower::getHeight() const {
    return height;
}

现在我正在尝试测试代码以查看运算符重载是否正常工作:

void test() {
    Card card (Card::SOUTH, 3);
    Tower tower(card);

    std::cout << "Printing tower: " << tower << std::endl;  //PRINTS OUT 3 AS EXPECTED

    Card one (Card::NORTH, 2);
    Card two (Card::WEST, 3);

    std::cout << "Expecting to receive an error: " <<endl;
    tower.demolish(one);

    std::cout << "Expecting to have the tower demolished: ";
    std::cout << tower.demolish(two) <<std::endl;

    std::cout << "Height of the tower: " << tower.getHeight() <<std::endl;

    std::vector<Item> items;       //creating an Item vector
    items.push_back(Tower(one));

    Item items2[1];                //creating an array of Items
    items[0]= tower;

    std::cout << "Printing out an Item: ";    
    std::cout << items.back()<<std::endl;   //EXPECTING TO GET 2 BUT IT PRINTS NOTHING, WHY IS THAT?
    std::cout << "OR: " << items2[0]<<std::endl;  //SAME ISSUE HERE, EXPECTING TO GET 3
}

从代码中可以理解,一张卡片包含一个整数值distance和一个枚举值direction。如果我也包含该代码,那将是一团糟。我已经在最后一段代码 test() 中评论了我的问题。提前感谢您的帮助。

【问题讨论】:

  • ¤ Item items2[1] 创建一个包含一个 Item 对象的数组。当您在那里复制Tower 对象时,复制的只是Item 基类子对象。这称为切片。该副本属于Item 类型。这些位(在您的情况下是零位,但没关系)不记得它们是从派生类型的对象复制的,特别是对于几乎每个 C++ 实现的工作方式, 对象中的vtable指针指向Item类vtable。干杯&hth.,

标签: c++ inheritance operator-overloading ostream


【解决方案1】:
std::vector<Item> items;       //creating an Item vector
items.push_back(Tower(one));

这里发生的事情称为“切片”。由于您存储的不是指针,而是实际对象,因此类的 Tower 部分只是被切断,只有 Item 部分被推入向量中。要使用虚函数和多态,您需要一个指向基类的引用或指针。

std::vector<Item*> items;       //creating an Item vector
items.push_back(new Tower(one));
// ...
// at the end of main:
for(int i=0; i < items.size(); ++i)
  delete items[i];

或者使用来自 Boost 或 C++11 库的智能指针

std::vector<shared_ptr<Item>> items;
items.push_back(make_shared<Tower>(one));
// nothing further needs to be done

对于打印,您现在显然需要取消引用指针:

std::cout << "Printing out an Item: ";    
std::cout << *items.back()<<std::endl;
std::cout << "OR: " << *items2[0]<<std::endl;

}

【讨论】:

  • 有趣,我不知道。非常感谢@Xeo
  • @Amino Acid:如果这个答案解决了你的问题,你应该点击它旁边的小勾号。 :)
猜你喜欢
  • 1970-01-01
  • 2011-12-05
  • 2013-10-10
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多