A downcast is the conversion of a Base* to a Derived*, where class Derived is publicly derived from class Base. A downcast is used when the client code thinks (or hopes!) that a Base* points to an object of class Derived or a class derived from Derived and it needs to access a member function that is provided by Derived but not by Base. For example, suppose class LiquidAsset is derived from class Asset, and LiquidAsset is a derived class that is liquidatable but Asset itself is not liquidatable. A downcast from an Asset* to a LiquidAsset* allows the liquidation. #include <iostream> using namespace std; class Asset { public: virtual ~Asset() throw(); virtual bool isLiquidatable() const throw(); }; Asset::~Asset() throw() { } bool Asset::isLiquidatable() const throw() { return false; } class LiquidAsset : public Asset { public: LiquidAsset(int value=100) throw(); int getValue() const throw(); void setValue(int value) throw(); virtual bool isLiquidatable() const throw(); protected: int value_; //value of this asset }; LiquidAsset::LiquidAsset(int value) throw() : value_(value) { } int LiquidAsset::getValue() const throw() { return value_; } void LiquidAsset::setValue(int value) throw() { value_ = value; } bool LiquidAsset::isLiquidatable() const throw() { return true; } int tryToLiquidate(Asset& asset) throw() { int value; if (asset.isLiquidatable()) { LiquidAsset& liquidAsset = (LiquidAsset&) asset; value = liquidAsset.getValue(); liquidAsset.setValue(0); cout << "Liquidated $" << value << '\n'; } else { value = 0; cout << "Sorry, couldn't liquidate this asset\n"; } return value; } int main() { Asset a; LiquidAsset b; tryToLiquidate(a); tryToLiquidate(b); } The output of this program follows. Sorry, couldn't liquidate this asset Liquidated $100 Although dynamic_cast (see FAQ 27.17) can eliminate the unsafe casts, it cannot eliminate the nonextensible control flow logic. See FAQ 27.12 for a better alternative. |