Casting

Casting is when you convert one variable to another type, or derived class type. For example, if you want to convert a floating point number e.g. 3.4 to a integer value 3 you would need to cast that floating point number to a integer because the compiler cannot return to a variable that is not of the same type as the result on the right had side of the command line.

C style

The classic C style of casting is to put the casting return type in brackets and then place the variable that you want to cast on the right hand side. Example code would be

float fl = 3.4;
int intFl = (int)fl;

which would result in the intFl value being 3, the 0.4 is disregarded because it is not part of a integer value (only whole numbers, it will round down always).

Different types of casting

There are different types of casting variables from one to another, here is a list of casting types

const_cast
static_cast
dynamic_cast
reinterpret_cast

And all follow the same parameters

return value = casting_type<return type>(casting value)
e.g.
int value = static_cast<int>(floatvalue);

From the c++ language, these allows for better type checking after you have cast the variable.

const_cast

Constant casting is the way of removing a constant restriction from a variable, sometimes you may want to alter a value that is held within a constant value.

const int coffee = 3;
int &newCoffees = const_cast<int&>(coffee);
newCoffees += 2;
// you can now add more coffees to your day.

One of the functions within C++ is strstr which returns a pointer to a subpart of the string, the string to search is a constant with the string to search for within the string is also a constant, but you need to return a normal char * to where the subpart of the string is.

Here is code similar to the strstr that will hopefully show a const_cast is abit more usable way.

#include <iostream>
#include <string.h>

using namespace std;

char* genuxStrStr(const char* p1, const char* p2)
{
      bool found;
     // loop through the first string
      while (*p1)
      {
	  // if there is a match between the frist string character and the second string character
	  if (*p2 == *p1)
	  {
	    if (strlen(p2) <= strlen(p1))
	    {
	      found = true;
	      for (int i =0; i < strlen(p2); i++)
	      {
		if (p2[i] != p1[i]) {
		  found = false;
		  break;
		}
	      }
	      if (found) 
	      {
		return const_cast<char*>(p1);
	      }
	    }
	  }
	  p1++;
      }
      return 0;
}

int main()
{
    char searchStr[] = "hi thre there k ";
    char *pr = genuxStrStr(searchStr, "there");

    // check to make sure it was found.
    if (pr)
    {
      cout << pr << endl;
    }
    else
      cout << "no found" << endl;
}

where the return would be

there k

because that is the first occurrence of the word there within the string.

static_cast

The static cast is mainly used for conversion between normal types, e.g. int, float, double, it can do pointers and also other variables types but the type checking is not as good as a dynamic_cast if you are going to convert between classes.

The basics of the code would be something similar to

int pi = 3;
float piF = static_cast<float>(pi);

this will convert from a integer value to a floating point value, without hopefully any bad effects, this is very similar to the C style of conversion, but this has more type checking involved.

dynamic_cast

Dynamic casting is when you want to convert from one class to another, but the only restriction is that the base class has to be polymorphic (e.g. have a virtual method).

Here is a example base class

class basicClass {
    private :
       int x;
    public:
       basicClass() { x = 0;}    
       void setX(int value ) { x = value;}

       virtual int returnX() { cout << "hi from there from the base"; return x;}

};

and here would be a basic sub class that is inheriting from the basic class

class subClass : public basicClass {
   private : 
     int y;
   public : 
     subClass() : basicClass() { y = 0; }
     // new Y to the class
     void setY(int value) { y = value;}
     int returnY() { return y;}

     int returnX() { cout << "Hi from the sub class" << endl; return x;}
};

the sub class has also implemented a "y" variable that is very similar to the X in that you can get/set it, but the returnX function also will display which class it is coming from.

If you wanted to create a sub class(subClass) and then convert to the base class (basicClass) as

subClass *sub = new subClass();
sub->setX(10);
sub->setY(20);
basicClass *basic = new dynamic_cast<basicClass*>(sub);

cout << basic->returnY();

Also the above code would output "hi from the subclass" since that is the actual class that you are really talking to.

the y value is still held within the base class that has been casted to, but you cannot "see" it from the base class calls since there is none in that class, but if you cast back to a subclass you can access the "y" again, because the cast will convert the sub class object into the similar base class (whilst still pointing to the same place in memory) since both have similar things in common.

subClass *myNewSub = dynamic_cast<subClass>(basic);
cout << myNewSub->returnY();

that would return the Y value of 20 since it has cast the memory back to a subClass structure and in that structure in memory Y equaled 20.

To check the result you just check return value against 0 (NULL) because if has not been able to cast the type it will return 0.

if (myNewSub == 0)
// dynamic_cast did not work

When you are casting from a derived class you do not need to dynamic cast because it does not need to "add" anything to the memory location as such, because the area within the memory is big enough to use the base class of the subclass, for example

subClass *sub = new subClass();
sub->setX(10);
sub->setY(20);

// there is no need for a dynamic casting.
basicClass *basic = sub;

cout << basic->returnY();

you only need to dynamic_cast when you are moving up the chain of inheritance.

You can also check for any bad casting with using a try and catch block, for example

try {
    *base = dynamic_cast<int>(intvalue);
}
catch (std::bad_cast)
{
    cout << "there was a bad_cast here!!" << endl;
}

reinterpret_cast

The reinterpret_cast does not really do any type checking apart from does the returning type fit into the bit pattens of the casting type, and that is about it. You can convert a class to a void and then back again without any problems, and also ClassA into a void and then into ClassB, but if ClassB was not similar to ClassA it would just come back with funny data.

  int *aInt = new int(10);
  void *bVoid = reinterpret_cast<void*>(aInt);
  float *aFloat = reinterpret_cast<float*>(bVoid);

the aFLoat pointer will be a float variable but the value could be anything, I just did it and the result was 1.4013e-44, which 1e1 equals 10. Where as the dynamic_cast would try and see if the float (aFloat) is similar to the aInt types.

Conclusion

I would personally only with dynamic_cast for classes and static_cast'ing for fundamental types like int, float etc. Better to use the c++ casting methods because at least there is some fundamental checks.

I do really like to have any feedback regarding any tutorial/post, just reply or PM me.. glad to help, better to share knowledge.

This page was published on It was last revised on

0

0 Comments

  • Votes
  • Oldest
  • Latest