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

Comments
No Comments »
Categories
Coding
Tags
C++, Class, Design, Down-cast, Structure, Virtual Function
Comments rss Comments rss
Trackback Trackback

Derived class issues with arrays and casting in C++

r3dux | January 29, 2012

I’m working my way through C++ FAQs book by Cline and Lomow, and it’s excellent. There’s lots of issues going on with inheritance, arrays and casting that could be a real pain to deal with towards the end of system development, but that you can nip in the bud and make life easier for yourself. For example, just knowing that an array of objects of a Derived class is NOT a kind-of array of objects of the Base class can prevent you a lot of headaches…

// Book: C++ FAQs by Cline & Lomow
// FAQ 136 & 137 - Is array-of Derived a kind-of array-of Base?
// Answer: NO!
 
#include <iostream>
using namespace std;
 
class Base
{
	protected:
		int i;
 
	public:
		Base() : i(42*42)      { }
		virtual ~Base()        { }
		virtual void service() { cout << "Base::service() called.\n" << flush; }
};
 
class Derived : public Base
{
	protected:
		// Add some extra things so that an object of type Derived is a different
		// size to an object of type Base
		int j;
		float k;
		unsigned long l;
 
	public:
		Derived() : Base(), j(42*42*42) { }
		virtual void service()          { cout << "Derived::service() called.\n" << flush; }
};
 
// Userland function
void useSubscript(Base *b)
{
	cout << "b[0].service(): " << flush; b[0].service();
	cout << "b[1].service(): " << flush; b[1].service(); // BOOM! Segfault!
 
	// This fails because the size of Base and the size of Derived are different:
	// "The fundamental problem is that a pointer to the first of an array-of-things
	// has exactly the same type as a pointer to a single thing. This was inherited
	// from C."
	//
	// In essence, as we're passing in Base pointers, in this case Base moves from
	// element to element in 16 byte intervals, but we actually provided an array
	// of Derived objects, which have a size of 32 bytes each, so b[1] starts
	// at b[0]+16, which is really only half-way through our first Derived element d[0]!
	//
	// The way to do this properly is to use a templatised container class instead.
	// If you tried to pass Array<Derived> as Array<Base> this would be caught at compile time.
}
 
int main()
{
    Derived d[10];
 
    cout << "Base has a size of   : " << sizeof(Base)    << " bytes." << endl;         // 16 bytes
    cout << "Derived has a size of: " << sizeof(Derived) << " bytes." << endl << endl; // 32 bytes
 
    useSubscript(d);
 
    return 0;
}

Good to know – now I just have to keep it in mind when I’m coding!

Comments
No Comments »
Categories
Coding
Tags
Array, Base, C++, Class, Crash, Derived, Kind-Of, Segfault
Comments rss Comments rss
Trackback Trackback

Sebastian Thrun is Awesome

r3dux | November 19, 2011

I’m doing the Stanford online AI class this year, taught by Professor’s Sebastian Thrun and Peter Norvig. And up in week 5, unit 11 is Markov Decision Processes (MDPs), Hidden Markov Models (HMMs) and State Transition Probabilities. Sounds dry, right?

Check this out…

YouTube Preview Image

Oh. My. God.

As a teacher myself, and one who genuinely tries hard to interest and engage students, Sebastian is a role-model. How absolutlely RARING-TO-GO is he?! To paraphrase: “I CAN’T WAIT to teach you all about this, and that, and this other cool shit! And you can use it for all kinds of neat stuff! Woo-hoo!” =DDD

And yeah, the course isn’t easy, and it requires time and effort and commitment – but it’s fun! And it’s rewarding, and I’m inspired as a student, and blown-away as a teacher.

If more teachers had this kind of passion, I sincerely believe that the world would be an entirely different place.

Comments
No Comments »
Categories
Life
Tags
AI, AIClass, Class, Optimism, Sebastian Thrun, Teaching
Comments rss Comments rss
Trackback Trackback

An introduction to ActionScript 3.0 – week 6

r3dux | April 26, 2011

Week 6 of the ActionScript intro carries on with the theme of coding rather than just talking about coding and as such again comes as a word document instead of slides. This week is where we start to have some fun with classes and dynamic creation of symbol instances. We start off by binding a bubble image to a simple class, and then tie it into the mouse cursor position, add in some colour transforms to liven things up and and stop our instances from giving you eye cancer by making them fade in and out through some manipulation of the each instance’s alpha property.

In this bundle I’ve combined both Week 6 Lessons 1 and 2 into a single document and provided the full source code to the exercises, but I highly recommend that you either start from scratch using the document as a guide or work from the 1st example source code and only peek at the completed source code if you get stuck because if you’re reading this then you want to learn to code, and you’re not going accomplish that by copying and pasting alone.

By the end of this tutorial, you’ll be able to build this:

Not a bad starting point for moving onto some way cooler stuff, eh?

Download link: An Introduction to ActionScript 3.0 – Week 6 (both lessons combined)
Audience: Beginners who know a little about variables, functions, objects and how to perform some basic programming math.
Format: PDF
Content License: This material is released under a creative commons non-commercial attribution share-alike 3.0 license by me (r3dux) and comes with no guarantee of correctness, fitness for purpose or anything of the sort.

Comments/feedback always welcome.

Bonus: You can find the code for the above animation with the start/stop on click code here.

Comments
No Comments »
Categories
Coding
Tags
ActionScript, alpha, Class, ColorTransform, cursor, Flash, Mouse, Opacity, position
Comments rss Comments rss
Trackback Trackback

ActionScript 3: How to use Event Listeners to Call Functions with Parameters

r3dux | May 15, 2010

By default, you can’t. But there’s a way around it so you can by creating a custom event class! In this case, I’m going to deal with extending the Timer class to create a custom timer class with additional properties that we can use to pass data to functions.

The Problem

To demonstrate the problem, consider the following simple timer code:

var greetTimer:Timer = new Timer(3000, 1);
greetTimer.addEventListener(TimerEvent.TIMER, greet);
greetTimer.start();
 
function greet(e:TimerEvent):void
{
	trace("Hello!");
}

This will work just fine – it’ll call the greet function once to output “Hello!” three seconds after the timer was started. But what if I wanted to say “Hello, SOME_NAME_STRING”, like “Hello, Bob!”, well you might think you could just do something like this:

var name:String = "Bob";
 
var greetTimer:Timer = new Timer(3000);
greetTimer.addEventListener(TimerEvent.TIMER, greet(name));
greetTimer.start();
 
function greet(e:TimerEvent, theName:String):void
{
	trace("Hello, " + theName + "!");
}

But you CAN’T! ActionScript 3 doesn’t allow you to pass parameters other than the TIMER event (i.e. the timer going off) to functions which are bound to a timer. And even changing the order of the parameters, or using a line such as the one below simply won’t work:

greetTimer.addEventListener(TimerEvent.TIMER, greet, name);

The Solution

Now, there are things you can do like use intermediate functions which might call a second function, or using anonymous in-line functions (there’s a good forum thread on it here if you want to investigate that route) – but there’s a better way of doing it: We can just create our own custom Timer class!

For this simple text example we could use something like this:

Custom Timer Class (String version) Code:

package
{
	// Import required libraries
	import flash.utils.Timer;
 
	public class cTimer extends Timer
	{
		// Create a property for our cTimer class which can be used to store a String
		public var firstName:String;
 
		// Constructor function
		public function cTimer(theDelay:Number, theRepeatCount:int, theFirstName:String):void
		{
			// Create a normal timer using the Timer class' constructor
			super(theDelay, theRepeatCount);
 
			// Set our firstName property to what was passed to our cTimer constructor
			this.firstName = theFirstName;
 
		} // End of constructor
 
	} // End of class
 
} // End of package

And then we could use our custom timer like this:

Flash File Code:

// Import our custom timer class for use
import cTimer;
 
var greetTimer:Timer = new cTimer(3000, 1, "Bob");
greetTimer.addEventListener(TimerEvent.TIMER, greet);
greetTimer.start();
 
function greet(e:TimerEvent):void
{
	trace("Hello, " + e.currentTarget.firstName + "!");
}

This will print out “Hello, Bob!” just fine using the additional property in our custom timer class! :)

Now that’s all well and good, but most people want to modify some manner of DisplayObject (Sprite, MovieClip etc.) when the timer fires, so for that we can just modify our custom timer class to expect a DisplayObject like this:

Custom Timer Class (DisplayObject version) Code:

package
{
	// Import required libraries
	import flash.utils.Timer;
	import flash.display.DisplayObject;
 
	public class cTimer extends Timer
	{
		// Create a property for our cTimer class which can be used to store a DisplayObject
		public var timerTarget:DisplayObject;
 
		// Constructor function
		public function cTimer(theDelay:Number, theRepeatCount:int, theTimerTarget:DisplayObject):void
		{
			// Create a normal timer using the Timer class' constructor
			super(theDelay, theRepeatCount);
 
			// Set our timerTarget to what was passed to our cTimer constructor
			this.timerTarget = theTimerTarget;
 
		} // End of constructor
 
	} // End of class
 
} // End of package

Flash File Code:

// Import our custom timer class for use
import cTimer;
 
// Create a simple circle centered on the stage and fully transparent
var circle_mc:Circle = new Circle();
circle_mc.x = 275;
circle_mc.y = 200;
circle_mc.alpha = 0;
addChild(circle_mc);
 
// Create a custom timer which does everything a timer does, but also stores a DisplayObject
var circleFadeInTimer:cTimer = new cTimer(2000, 1, circle_mc);
circleFadeInTimer.addEventListener(TimerEvent.TIMER, fadeIn);
circleFadeInTimer.start();
 
// Function to make the circle visible
function fadeIn(e:TimerEvent):void
{
	// Using our timerTarget property of our custom timer class (cTimer) modify the DisplayObject
	e.currentTarget.timerTarget.alpha = 1;	
}

Note: The above code assumes you’ve created a symbol with the class name “Circle” – to do so just draw a circle on the stage, stab F8 to convert it to a symbol, and check the Export for ActionScript checkbox and enter Circle as the class name before hitting the [OK] button.

Just like our String example, adding the additional property to our custom timer class allows us to bind the timer to a specific object which we can then manipulate from the function called when the timer fires! So in this case, two seconds after the timer starts our fadeIn function will be called and our circle instance will have its alpha property set to 1 (so it’s fully opaque – hence visible!).

Wrap Up

I came up against this problem whilst helping out some of my ActionScript students who are first-time coders, so wanted to code more Procedurally than Object-Oriented. When you use OOP there are better ways of going about things, but this is still a useful trick to know when you’re dealing with Event Listeners and Timers. I hope it helps out anyone who’s been banging their head against this problem! Cheers!

Comments
1 Comment »
Categories
Coding
Tags
ActionScript, addEventListener, Class, Custom, Events, Functions, Parameters, Pass, Passing, Timer, TimerEvent
Comments rss Comments rss
Trackback Trackback

« Previous Entries

Translate

Categories

Archives

Tags

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

Gamercard

OpenR3dux

Misc.

Flattr this

RSS Feed

r3dux twitter feed



“Please pay attention as we may not have long together.”

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