opérateur ostream surcharge - héritage
-
27-10-2019 - |
Question
J'ai une classe de base appelée Point :
#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
et j'ai une classe dérivée Tour :
#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
Le code source pour Tour :
#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;
}
Maintenant, je suis en train de tester le code pour voir si la surcharge d'opérateur fonctionne correctement:
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
}
Comme on peut le comprendre à partir du code, une carte contient une valeur entière distance et une valeur de enum direction . Il aurait été un gâchis si j'inclus ce code aussi. Je l'ai commenté mes questions dans le dernier morceau de code test () . Merci pour votre aide à l'avance.
La solution
std::vector<Item> items; //creating an Item vector
items.push_back(Tower(one));
Qu'est-ce qui se passe ici est appelé « trancher ». Puisque vous n'êtes pas stocker des pointeurs, mais des objets réels, la partie Tower
de la classe est juste coupée et seule la partie Item
est poussé dans le vecteur. Pour utiliser les fonctions virtuelles et polymorphisme, vous avez besoin d'une référence ou pointeur vers la classe de base.
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];
Ou avec des pointeurs intelligents de Boost ou une bibliothèque C ++ 11
std::vector<shared_ptr<Item>> items;
items.push_back(make_shared<Tower>(one));
// nothing further needs to be done
Pour l'impression, vous maintenant besoin évidemment de déréférencer le pointeur:
std::cout << "Printing out an Item: ";
std::cout << *items.back()<<std::endl;
std::cout << "OR: " << *items2[0]<<std::endl;
}