2011-12-04 18 views
0

私は項目と呼ばれる基本クラスがあります。のostream演算子のオーバーロード - 継承

#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 

を、私はタワー派生クラスを持っている:タワーため

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

コードから理解できるように、カードが整数値距離と列挙値方向を保持しています。もし私がそのコードを含んでいれば混乱していたでしょう。私はコードの最後の部分で私の質問をコメントしましたtest()。あなたの助けを前もってありがとう。

+1

¤ 'item items2 [1]'は、 'Item'オブジェクトの配列を作成します。そこに 'Tower'オブジェクトをコピーすると、' Item'基本クラスのサブオブジェクトがコピーされます。それは**スライシング**と呼ばれています。コピーは 'Item'型です。これらのビット(あなたのケースではビット数はゼロですが、それは関係ありません)は、派生型のオブジェクトからコピーされたことを覚えていません。特に、ほぼすべてのC++実装が動作する方法、* vtableポインタオブジェクト内の*は 'Item'クラスvtableを指します。乾杯、 –

答えて

3
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]; 

や印刷のためにブーストまたは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; 

}

+0

興味深い、私はそれを知らなかった。ありがとう@Xeo – Radix

+0

@Amino Acid:この答えがあなたの問題を解決した場合は、それの右の小さな目盛りをクリックする必要があります。 :) – Xeo

関連する問題