|
C++ Programming Tutorials
static_cast
static_cast can perform conversions between pointers to related classes,
not only from the derived class to its base, but also from a base class
to its derived. This ensures that at least the classes are compatible if
the proper object is converted, but no safety check is performed during
runtime to check if the object being converted is in fact a full object
of the destination type. Therefore, it is up to the programmer to ensure
that the conversion is safe. On the other side, the overhead of the
type-safety checks of dynamic_cast is avoided.
class CBase {};
class CDerived: public CBase {};
CBase * a = new CBase;
CDerived * b = static_cast<CDerived*>(a); |
This would be valid, although b would point to an incomplete
object of the class and could lead to runtime errors if dereferenced.
static_cast can also be used to perform any other non-pointer conversion that
could also be performed implicitly, like for example standard conversion between
fundamental types:
double d=3.14159265;
int i = static_cast<int>(d); |
Or any conversion between classes with explicit constructors
or operator functions as described in "implicit conversions" above.
reinterpret_cast
reinterpret_cast converts any pointer type to any other pointer type, even of
unrelated classes. The operation result is a simple binary copy of the value
from one pointer to the other. All pointer conversions are allowed: neither the
content pointed nor the pointer type itself is checked.
It can also cast pointers to or from integer types. The format in which this
integer value represents a pointer is platform-specific. The only guarantee is
that a pointer cast to an integer type large enough to fully contain it, is
granted to be able to be cast back to a valid pointer.
The conversions that can be performed by reinterpret_cast but not by static_cast
have no specific uses in C++ are low-level operations, whose interpretation
results in code which is generally system-specific, and thus non-portable. For
example:
class A {};
class B {};
A * a = new A;
B * b = reinterpret_cast<B*>(a); |
This is valid C++ code, although it does not make much sense,
since now we have a pointer that points to an object of an incompatible class,
and thus dereferencing it is unsafe.
const_cast
This type of casting manipulates the constness of an object, either to be set or
to be removed. For example, in order to pass a const argument to a function that
expects a non-constant parameter:
// const_cast
#include <iostream>
using namespace std;
void print (char * str)
{
cout << str << endl;
}
int main () {
const char * c = "sample text";
print ( const_cast<char *> (c) );
return 0;
} |
sample text
|
typeid
typeid allows to check the type of an expression:
typeid (expression)
This operator returns a reference to a constant object of type type_info that is
defined in the standard header file <typeinfo>. This returned value can be
compared with another one using operators == and != or can serve to obtain a
null-terminated character sequence representing the data type or class name by
using its name() member.
// typeid
#include <iostream>
#include <typeinfo>
using namespace std;
int main () {
int * a,b;
a=0; b=0;
if (typeid(a) != typeid(b))
{
cout << "a and b are of different types:\n";
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
}
return 0;
} |
a and b are of
different types:
a is: int *
b is: int
|
When typeid is applied to classes typeid uses the RTTI to
keep track of the type of dynamic objects. When typeid is applied to an
expression whose type is a polymorphic class, the result is the type of the most
derived complete object:
// typeid, polymorphic class
#include <iostream>
#include <typeinfo>
#include <exception>
using namespace std;
class CBase { virtual void f(){} };
class CDerived : public CBase {};
int main () {
try {
CBase* a = new CBase;
CBase* b = new CDerived;
cout << "a is: " << typeid(a).name() << '\n';
cout << "b is: " << typeid(b).name() << '\n';
cout << "*a is: " << typeid(*a).name() << '\n';
cout << "*b is: " << typeid(*b).name() << '\n';
} catch (exception& e) { cout << "Exception: " << e.what() << endl; }
return 0;
} |
a is: class CBase *
b is: class CBase *
*a is: class CBase
*b is: class CDerived
|
Notice how the type that typeid considers for pointers is the
pointer type itself (both a and b are of type class CBase *). However, when
typeid is applied to objects (like *a and *b) typeid yields their dynamic type
(i.e. the type of their most derived complete object).
If the type typeid evaluates is a pointer preceded by the dereference operator
(*), and this pointer has a null value, typeid throws a bad_typeid exception.
NEXT >> Preprocessor Directives
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.
|