|
C++ Programming Tutorials
Type Casting
Converting an expression of a given type into another type is known as
type-casting. We have already seen some ways to type cast:
Implicit conversion
Implicit conversions do not require any operator. They are automatically
performed when a value is copied to a compatible type. For example:
short a=2000;
int b;
b=a; |
Here, the value of a has been promoted from short to int and
we have not had to specify any type-casting operator. This is known as a
standard conversion. Standard conversions affect fundamental data types, and
allow conversions such as the conversions between numerical types (short to int,
int to float, double to int...), to or from bool, and some pointer conversions.
Some of these conversions may imply a loss of precision, which the compiler can
signal with a warning. This can be avoided with an explicit conversion.
Implicit conversions also include constructor or operator conversions, which
affect classes that include specific constructors or operator functions to
perform conversions. For example:
class A {};
class B { public: B (A a) {} };
A a;
B b=a; |
Here, a implicit conversion happened between objects of class
A and class B, because B has a constructor that takes an object of class A as
parameter. Therefore implicit conversions from A to B are allowed.
Explicit conversion
C++ is a strong-typed language. Many conversions, specially those that imply a
different interpretation of the value, require an explicit conversion. We have
already seen two notations for explicit type conversion: functional and c-like
casting:
short a=2000;
int b;
b = (int) a; // c-like cast notation
b = int (a); // functional notation |
The functionality of these explicit conversion operators is
enough for most needs with fundamental data types. However, these operators can
be applied indiscriminately on classes and pointers to classes, which can lead
to code that while being syntactically correct can cause runtime errors. For
example, the following code is syntactically correct:
// class type-casting
#include <iostream>
using namespace std;
class CDummy {
float i,j;
};
class CAddition {
int x,y;
public:
CAddition (int a, int b) { x=a; y=b; }
int result() { return x+y;}
};
int main () {
CDummy d;
CAddition * padd;
padd = (CAddition*) &d;
cout << padd->result();
return 0;
} |
|
The program declares a pointer to CAddition, but then it
assigns to it a reference to an object of another incompatible type using
explicit type-casting:
Traditional explicit type-casting allows to convert any
pointer into any other pointer type, independently of the types they point to.
The subsequent call to member result will produce either a run-time error or a
unexpected result.
In order to control these types of conversions between classes, we have four
specific casting operators: dynamic_cast, reinterpret_cast, static_cast and
const_cast. Their format is to follow the new type enclosed between
angle-brackets (<>) and immediately after, the expression to be converted
between parentheses.
dynamic_cast <new_type> (expression)
reinterpret_cast <new_type> (expression)
static_cast <new_type> (expression)
const_cast <new_type> (expression)
The traditional type-casting equivalents to these expressions would be:
(new_type) expression
new_type (expression)
but each one with its own special characteristics:
dynamic_cast
dynamic_cast can be used only with pointers and references to objects. Its
purpose is to ensure that the result of the type conversion is a valid complete
object of the requested class.
Therefore, dynamic_cast is always successful when we cast a class to one of its
base classes:
class CBase { };
class CDerived: public CBase { };
CBase b; CBase* pb;
CDerived d; CDerived* pd;
pb = dynamic_cast<CBase*>(&d); // ok: derived-to-base
pd = dynamic_cast<CDerived*>(&b); // wrong: base-to-derived |
The second conversion in this piece of code would produce a
compilation error since base-to-derived conversions are not allowed with
dynamic_cast unless the base class is polymorphic.
When a class is polymorphic, dynamic_cast performs a special checking during
runtime to ensure that the expression yields a valid complete object of the
requested class:
// dynamic_cast
#include <iostream>
#include <exception>
using namespace std;
class CBase { virtual void dummy() {} };
class CDerived: public CBase { int a; };
int main () {
try {
CBase * pba = new CDerived;
CBase * pbb = new CBase;
CDerived * pd;
pd = dynamic_cast<CDerived*>(pba);
if (pd==0) cout << "Null pointer on first type-cast" << endl;
pd = dynamic_cast<CDerived*>(pbb);
if (pd==0) cout << "Null pointer on second type-cast" << endl;
} catch (exception& e) {cout << "Exception: " << e.what();}
return 0;
} |
Null pointer on
second type-cast
|
The code tries to perform two dynamic casts from pointer
objects of type CBase* (pba and pbb) to a pointer object of type CDerived*, but
only the first one is successful. Notice their respective initializations:
CBase * pba = new CDerived;
CBase * pbb = new CBase; |
Even though both are pointers of type CBase*, pba points to
an object of type CDerived, while pbb points to an object of type CBase. Thus,
when their respective type-castings are performed using dynamic_cast, pba is
pointing to a full object of class CDerived, whereas pbb is pointing to an
object of class CBase, which is an incomplete object of class CDerived.
When dynamic_cast cannot cast a pointer because it is not a complete object of
the required class -as in the second conversion in the previous example- it
returns a null pointer to indicate the failure. If dynamic_cast is used to
convert to a reference type and the conversion is not possible, an exception of
type bad_alloc is thrown instead.
dynamic_cast can also cast null pointers even between pointers to unrelated
classes, and can also cast pointers of any type to void pointers (void*).
NEXT >>
static_cast
Have a Question ?
post your questions here. It
will be answered as soon as possible.
Check
C Aptitude Questions
for more C Aptitude Interview Questions with Answers
Check
C Interview Questions
for more C Interview Questions with Answers.
|