// ========================================================================== // $Id: down_cast.cpp,v 1.6 2011/09/10 01:08:19 jlang Exp $ // CSI2372 example Code for lecture 7 // ========================================================================== // (C)opyright: // // Jochen Lang // SITE, University of Ottawa // 800 King Edward Ave. // Ottawa, On., K1N 6N5 // Canada. // http://www.site.uottawa.ca // // Creator: jlang (Jochen Lang) // Email: jlang@site.uottawa.ca // ========================================================================== // $Log: down_cast.cpp,v $ // Revision 1.6 2011/09/10 01:08:19 jlang // Updates F10 // // Revision 1.5 2008/10/15 22:01:20 jlang // Added exception handling // // Revision 1.4 2007/11/05 17:09:13 jlang // Added reference cases // // Revision 1.3 2007/11/05 16:55:25 jlang // extended example // // Revision 1.2 2007/11/05 16:14:28 jlang // Removed extra ^M // // Revision 1.1 2006/10/16 01:44:37 jlang // small caps names // // Revision 1.1 2006/10/16 01:36:18 jlang // Check in for lecture 7 // // // ========================================================================== #include using std::cout; using std::endl; using std::bad_cast; class Building { double d_sqft; int d_noRooms; float d_price; public: Building( double _sqft = 1000.0, int _noRooms = 3 ) : d_sqft( _sqft ), d_noRooms( _noRooms ), d_price( 0 ) {} int getNoRooms() { return d_noRooms; } virtual ~Building() { cout << "Building::~Building()" << endl; } void setPrice( float _price ) { d_price = _price; return; } float getPrice() const { return d_price; } virtual float calculateTax() const { return d_price * 0.15f; } protected: void setSqft( double _sqft ) { d_sqft = _sqft; } }; class House : public Building { int d_noOccu; public: House( int _noOccu = 2 ) :d_noOccu( _noOccu ) {} ~House() { cout << "House::~House()" << endl; } virtual float calculateTax() const { return getPrice() * 0.07f;} int getNoOccupants() { return d_noOccu; }; int getNoRooms(); void setSqft( double _sqft ); }; int House::getNoRooms(){ // Kitchen and Bathroom do not count return Building::getNoRooms() - 2; } void House::setSqft( double _sqft ) { // max 1500 per person if ( _sqft/d_noOccu > 1500.0 ) { _sqft = 1500.0 * d_noOccu; } Building::setSqft( _sqft ); } float tax( const Building& _build ) { float res = _build.calculateTax(); return res; } class OfficeTower : public Building { int d_noCoffeeShops; public: OfficeTower( double _sqft = 50000, int _noRooms = 50 ) : Building( _sqft, _noRooms), d_noCoffeeShops(1) {} ~OfficeTower() { cout << "OfficeTower::~OfficeTower()" << endl; } virtual float calculateTax() const { return getPrice() * 0.03f;} float getNoCoffeeShops() const { return d_noCoffeeShops; } }; class Cottage : public Building { public: Cottage( double _sqft = 500, int _noRooms = 1 ) : Building( _sqft, _noRooms){} ~Cottage() { cout << "Cottage::~Cottage()" << endl; } virtual float calculateTax() const { return getPrice() * 0.06f;} }; Building *buildingGenerator() { Building *res = new House(); res->setPrice(100000); return res; } void printProps( OfficeTower* myTower ) { cout << "Office tax (?): " << myTower->calculateTax() << endl; cout << "No of Coffee Shops: " << myTower->getNoCoffeeShops() << endl; return; } int main() { Building *myHouseAsBuilding = buildingGenerator(); // Compile time error (if not commented out): // myHouseAsBuilding->getNoOfOccupants(); // Using dynamic cast House *myHouse = dynamic_cast( myHouseAsBuilding ); // now functions as a house cout << "No of Occupants: " << myHouse->getNoOccupants() << endl; delete myHouseAsBuilding; // Make another house myHouseAsBuilding = buildingGenerator(); // Try to cast it to an office tower -- dynamic cast will return 0 OfficeTower* myTower = dynamic_cast( myHouseAsBuilding ); if ( myTower ) { printProps( myTower ); } else { cout << "myTower was not a tower!" << endl; } // Old style cast will always work and fail later (or just turn up nonsense) myTower = (OfficeTower*) myHouseAsBuilding; if ( myTower ) printProps( myTower ); delete myTower; // Old style cast will always work and fail later (or just turn up nonsense) OfficeTower& myRefA = (OfficeTower&) *buildingGenerator(); // Try to cast it to an office tower -- with references // dynamic cast can't return 0; will throw an exception try { OfficeTower& myRefB = dynamic_cast( *buildingGenerator() ); } catch(bad_cast bc) { cout << "Down cast from Building to Office Tower failed!" << endl; } return 0; }