Constant casting

Constant casting is when you are for example calling a external library function that does not understand the const (constant) type and so you will need to take it off because the program will do something funny otherwise, crash. etc..

Here is a example code of a const_cast

#include <iostream>
 
using namespace std;
 
int exampleextenalfuction(int value)
{
	// you can alter the value if you want to, since it is not longer a constant value
	return value  + value;
}
 
int main()
{
	const int constvalue = 2;
 
	cout << constvalue << endl;
 
	cout << "Calling a external function that does not use constant types" << endl;
 
	cout << exampleextenalfuction(const_cast<int&>(constvalue)) << endl;
}

Static casting

Static casting is when you want to convert one type into another, static casting is used allot of the time without even knowing. For example

int value = 2;
float t = float(value);

the float(value) is a static casting of converting one value into another. Below is a full code example

#include <iostream>
 
using namespace std;
int main()
{
	int i = 3;
	// the float(<value)> is basically a static cast from a interger value into a float
	cout << float(i) << endl;
	cout << static_cast<float>(i) << endl;
}

It is very small since static_cast’ing is very basic in nature, but the only problem is that you have to check to make sure that there is a error e.g not NULL.

Execution order

Execution order of programs code is very much a vital thing to understand and where some fault finds will take a long while to figure out. Basically like in maths where there is a order of calculating, well in coding structures and also multitasking and multi-threading setups the execution order may be incorrect for lines of code.

Here is some examples, the first is when will a function be called and the later when post/pre incrementation will take place.

#include <iostream>
 
using namespace std;
 
int value =1;
 
int setvalue2()
{
	cout << "setting value"<<endl;
	value = 2;
	return value;
}
 
int returnvalue()
{
	cout << "renting value"<< endl;
	return value;	
}
 
int main()
{
	// depending on the order of execution the value may be
	/* setvalue2 called first
		(setvalue2 = 2 / returnvalue = 2) = 1
	   returnvalue called first
		(setvalue2 = 2 / returnvalue = 1) = 2
	*/
	cout << setvalue2() / returnvalue() << endl;
 
	int i;
	i = i++ - ++i;	// not sure what i will be because the pre/post increaments 
	i = 3, i++, i++; // i will equal 5 because in correct order.
}

Dynamic Casting

Dynamic casting, means that you can convert one object into another that is off the same type. For example, if you had a base class called Shape and a inherited class called Rectangle then you are able to convert a Shape object into a Rectangle.

Rectangle *rec = dynamic_cast<Shape *>(shapeobject);

sort of thing, there has to be a virtual function within the base class otherwise the compiler will complain, but apart from that that is about it.

Dynamic casting allows for NULL returns which is the best thing, because you can test to see if the casting actually worked and not to do anything silly on a NULL object which would crash the program.

Pointer casting uses the sytnax

<type> *p_subclass = dynamic_cast<<type> *>( p_obj );

Reference will not throw an error/expcetion so will need to check std::bad_cast< typeinfo header >, here is the syntax

<type> subclass = dynamic_cast<<type> &>( ref_obj );

Hopefully this will make more sense for how and why it works.

#include <iostream>
 
using namespace std;
 
class classA 
{
	public	:
		int x;		// should be private
		char y;		// should be private
 
		classA();
 
 		virtual ~classA() {}; 	// need to have a virtual function for dynamic casting
};
 
// basic classA constructor
classA::classA()
{ 
	cout << "classA" << endl; 
	x = 1; 
	y = 'a';
}
 
 
class classB : public classA
{	
	public :
		int b;		// should be private
 
		classB();
 
		~classB() {};	// complete the virtual
};
 
// basic classB constructor
classB::classB()
{
	cout << "classB" << endl;
	x = 2;
	y = 'b';
}
 
int main()
{
	classA newa;	// classA obj
	cout << "class A constructed" << endl;
	classB newb;	// classB obj
	cout << "class B constructed" << endl;
 
	cout << "NewA X " << newa.x << endl;
	cout << "NewB X " << newb.x << endl;
 
	// point a classB to a already created classB object
	classB *normalB = &newb;
	// dynamic_cast a normalB object (newb) to another classA object
	classA *dynA = dynamic_cast<classB *>(normalB);	
	cout << "dynamic A X " << dynA->x << endl;
 
	// does not work, because you cannot convert classA into a classB, but if classA was pointing to a classB type.
	classA *normalA = &newa;
	classB *dynB = dynamic_cast<classB *>(normalA);
	if (dynB)	// above produces a 0 because invalid.
	{
		cout << "dynamic B X " << dynB->x << endl;
		cout << "dynamic B X " << dynB->b << endl;
	}
 
	// this does work because it is converting from a pointer of classB type, which was "sitting" in a classA container
	// and then is converted back to a classB
	classA *normalA2 = &newb;
	classB *dynB2 = dynamic_cast<classB *>(normalA2);
	if (dynB2)	// above produces a 0 because invalid.
	{
		cout << "dynamic A2X " << normalA2->x << endl;	// output is 2 because it was a classB constructed
		cout << "dynamic B X " << dynB2->x << endl;
		cout << "dynamic B X " << dynB2->b << endl;
	}
 
}

Inheritance

Inherited classes allow for similar code to be re-used, this saves on code space and also development/testing time. Inherited classes basically have access to the internals of the “super” inherited class.

To create a inherited class
class sibling < superclass

And the sibling class can then call any methods etc within the superclass. The code example explains in code 😉

# base "Books" class
class Books
   # this is called within the .new class call
   def initialize(name, author, year)
       @name = name;
       @author = author;
       @year = year;
   end
 
   def to_s
          # return the to_s (to_string)
          "Books - Name #{@name} - Author #{@author} - Year #{@year}"
   end          
end
 
# this class is Inherited from the "Books" class
class BookToCD < Books
    def initialize(name, author, year, cdID)
           # use the "Books" class initlialize to setup the local variables within the super/inherited class
           super(name, author, year)
           #setup the local variables
           @cdID = cdID
    end
 
    def to_s
           # get the result from the super class
           result = super.to_s
           # return the result from the super class + the local cdID variable
           return result + " - CDID #{@cdID}" 
    end
end
# create a book
book = Books.new("Programming in Ruby", "Ruby Team", 2006)
# inspect outputs the internel structure of the class
puts book.inspect
puts book.to_s
 
booktocd = BookToCD.new("CD read of programming in Ruby", "Ruby Team",2006, 1)
# the inspect shows that the new class has a different memory address
puts booktocd.inspect
puts booktocd.to_s

Once executed on the command line the result is

#<Books:0x2777070 @year=2006, @name="Programming in Ruby", @author="Ruby Team">
Books - Name Programming in Ruby - Author Ruby Team - Year 2006
#<BookToCD:0x2776f38 @year=2006, @name="CD read of programming in Ruby", @cdID=1, @author="Ruby Team">
Books - Name CD read of programming in Ruby - Author Ruby Team - Year 2006 - CDID 1

As you can see the inspect method is showing that the memory block of the book and also booktocd are not the same even though they are sharing the same internals, this is Object Orientated.

Methods, Arrays, Hash

First part is the method and the second is the array and hash variables.

The manor in which Ruby returns values from a method is either by the return keyword or by the last executed line of code, thus if the result for the return of the method is the last line then there is no need to use the return keyword, but of course if the returnable value is calculated within the middle of the method and the rest is to clean up the method then use the return keyword.

# this is a basic method
def saySomething(name)
       result = "hi there #{name}"
       return result
end
 
# but Ruby will return the last evaluated line, thus this method
# is the same as the above one.
def saySomething2(name)
       "hi there #{name}"
end
 
# the two methods that are the same in there results
puts saySomething("Ian")
puts saySomething2("Ian Porter")

Below is how Ruby uses the array structure and also the hash structure, an array is defined within the [ ] brackets and the start of the array is 0, but within a hash since there is no start to the hash keys, then there is an hash key and then the values associated with that key. The hash structure is defined within { } brackets.

# this is a array
a = ['Gentoo Linux','is','great']
 
#this is a hash, an hash is a key -> value
has = { 'Gentoo' => 'Gentoo Linux',
       'RH' => 'Red Hat Linux'}       # hash
 
puts a[0]       # print the first element of the array
puts a              # print the arary
 
puts "The Key value of RH within the hash"
puts has['RH']       # print the value assoicated with the key RH
puts "The hash in full"
puts has

Once executed from the console, the output is

hi there Ian
hi there Ian Porter

for the first method demonstrating that the result value is the same

Gentoo Linux
Gentoo Linux
is
great
The Key value of RH within the hash
Red Hat Linux
The hash in full
RHRed Hat LinuxGentooGentoo Linux

Which shows the results of the program, this shows that the two methods return in the same manor and also an array is broken into separate blocks, but a hash has a continuous memory block in nature.

Class And Modules

A Ruby class is very similar to the other programming languages class structures. They allow for code to be created within a single object that can be reused etc, the code can have its own separate block of variables/methods for that instance of the required task. It is able to be inherited and extended which is different to a module which only allows for the created module to have methods and constant variables.

module SillyModule