r3dux.org

A number-pimping side project from the valleys in *NEW* upside-down flavour.

  • Home
  • ABOUT
  • OLD SITE
  • SEARCH
  • FEEDBACK

Avoiding down-casts in C++

r3dux | January 31, 2012

If you have to down-cast objects from a base class to a derived class then there’s probably a design flaw in the class structure. It might all work but it’s going to be a brittle design.

// C++ FAQS by Cline & Lowom
// FAQ 162 - What is a down-cast?
// Answer: Trouble.
 
#include <iostream>
 
using namespace std;
 
class Asset
{
	public:
		virtual ~Asset() { }
		virtual bool isLiquidatable() const { return false; } // BAD-FORM: Capability query
};
 
class LiquidAsset : public Asset
{
	protected:
		int mValue;
 
	public:
		LiquidAsset(int value = 100) : mValue(value) { }
 
		int getValue() const { return mValue; }
 
		void setValue(int theValue) { mValue = theValue; }
 
		virtual bool isLiquidatable() const { return true; } // BAD-FORM: Capability query
};
 
// Userland function to liquidate an asset (if it can)
int tryToLiquidate(Asset &asset)
{
	int value;
 
	if ( asset.isLiquidatable() )                     // BAD-FORM: Finds code using code
	{
		value = ((LiquidAsset&)asset).getValue(); // BAD-FORM: Down-cast
 
		((LiquidAsset&)asset).setValue(0);        // BAD-FORM: Down-cast
 
		cout << "Liquidated $" << value << endl;
	}
	else
	{
		value = 0;
		cout << "Sorry, couldn't liquidate this asset.\n";
	}
 
	return value;
}
 
int main()
{
    Asset       a;
    LiquidAsset b;
 
    tryToLiquidate(a);
    tryToLiquidate(b);
 
    return 0;
}

A better way to accomplish this is to give the users of your code the right tools in the first place as member functions, rather than them having to cobble together their own routines in userland:

// C++ FAQS by Cline & Lowom
// FAQ 163 - What is an alternative to using down-casts?
// Answer: An if/down-cast pair can often be replaced by a virtual function call. The key
// insight is to move the -context- of the capability query from the user's code into the
// virtual function; don't just move the primitive query used in the user's if statements.
 
#include <iostream>
using namespace std;
 
class Asset
{
	public:
		virtual ~Asset() { }
 
		virtual int tryToLiquidate()
		{
			cout << "Sorry, couldn't liquidate this asset.\n";
			return 0;
		}
};
 
class LiquidAsset : public Asset
{
	protected:
		int mValue;
 
	public:
		LiquidAsset(int value = 100) : mValue(value) { }
 
		int getValue() const { return mValue; }
 
		void setValue(int theValue) { mValue = theValue; }
 
		virtual int tryToLiquidate()
		{
			int value = mValue;
 
			mValue = 0;
 
			cout << "Liquidated $" << value << endl;
 
			return value;
		}
};
 
int main()
{
    Asset       a;
    LiquidAsset b;
 
    a.tryToLiquidate();
    b.tryToLiquidate();
 
    return 0;
}

Much better =D

Related posts:

  1. Derived class issues with arrays and casting in C++
  2. An example Abstract Factory design pattern implementation in C++
  3. An example implementation of the Strategy design pattern in C++
  4. How-To: Get valid integer input in C++ (a stupidly long solution to a stupidly simple problem)
  5. How to: convert any class to a Singleton with a template wrapper in C++
Categories
Coding
Tags
C++, Class, Design, Down-cast, Structure, Virtual Function
Comments rss
Comments rss
Trackback
Trackback
Print This Post Print This Post

« Derived class issues with arrays and casting in C++ Nada Surf – Enjoy the Silence (Depeche Mode cover) »

Leave a Reply

Click here to cancel reply.

Translate

Categories

Archives

Tags

3D ActionScript ActionScript 3.0 Adobe AI Ballarat Bash C++ Class Convert CS4 Effect Error Film Flash FPS GLFW Glitch GLSL Hack How-To install Java Kinect Linux Live Mash-Up Microsoft Motion mount OpenGL Particle Problem PS3 Remix Retro script Slides Sound Ubuntu Video VirtualBox Wii Windows XBox

Gamercard

OpenR3dux

Misc.

Flattr this

RSS Feed

r3dux twitter feed



“Put the needle to the record not the needle to the vein.”

 - Dilated Peoples

rss Comments rss valid xhtml 1.1 design by jide powered by Wordpress get firefox