Reference Links for C++
Casting operators in C++
C++ defines five casting operators.
The first is the traditional-style cast inherited from C.
The remaining four are
Function Pointers
A function pointer is a variable that stores the address of a function that can later be called through that function pointer. This is useful because functions encapsulate behavior. For instance, every time you need a particular behavior such as drawing a line, instead of writing out a bunch of code, all you need to do is call the function. But sometimes you would like to choose different behaviors at different times in essentially the same piece of code. Read on for concrete examples.
Functions as Arguments to Other Functions
If you were to write a sort routine, you might want to allow the function’s caller to choose the order in which the data is sorted; some programmers might need to sort the data in ascending order, others might prefer descending order while still others may want something similar to but not quite like one of those choices. One way to let your user specify what to do is to provide a flag as an argument to the function, but this is inflexible; the sort function allows only a fixed set of comparison types (e.g., ascending and descending).
A much nicer way of allowing the user to choose how to sort the data is simply to let the user pass in a function to the sort function. This function might take two pieces of data and perform a comparison on them. We’ll look at the syntax for this in a bit.
Callback Functions
Another use for function pointers is setting up “listener” or “callback” functions that are invoked when a particular event happens. The function is called, and this notifies your code that something of interest has taken place.
Why would you ever write code with callback functions? You often see it when writing code using someone’s library. One example is when you’re writing code for a graphical user interface (GUI). Most of the time, the user will interact with a loop that allows the mouse pointer to move and that redraws the interface. Sometimes, however, the user will click on a button or enter text into a field. These operations are “events” that may require a response that your program needs to handle. How can your code know what’s happening? Using Callback functions! The user’s click should cause the interface to call a function that you wrote to handle the event.
To get a sense for when you might do this, consider what might happen if you were using a GUI library that had a “create_button” function. It might take the location where a button should appear on the screen, the text of the button, and a function to call when the button is clicked. Assuming for the moment that C (and C++) had a generic “function pointer” type called function, this might look like this:
void create_button(int x, int y, const char *text, function callback_func);Whenever the button is clicked, callback_func will be invoked. Exactly what callback_func does depends on the button; this is why allowing the create_button function to take a function pointer is useful.
Function Pointer Syntax
The syntax for declaring a function pointer might seem messy at first, but in most cases it’s really quite straight-forward once you understand what’s going on. Let’s look at a simple example:
void (*foo)(int);In this example, foo is a pointer to a function taking one argument, an integer, and that returns void. It’s as if you’re declaring a function called “*foo”, which takes an int and returns void; now, if *foo is a function, then foo must be a pointer to a function. (Similarly, a declaration like int *x can be read as *x is an int, so x must be a pointer to an int.)
The key to writing the declaration for a function pointer is that you’re just writing out the declaration of a function but with (*func_name) where you’d normally just put func_name.
Reading Function Pointer Declarations
Sometimes people get confused when more stars are thrown in:
void *(*foo)(int *);Here, the key is to read inside-out; notice that the innermost element of the expression is *foo, and that otherwise it looks like a normal function declaration. *foo should refer to a function that returns a void * and takes an int *. Consequently, foo is a pointer to just such a function.
Initializing Function Pointers
To initialize a function pointer, you must give it the address of a function in your program. The syntax is like any other variable:
#include <stdio.h>
void my_int_func(int x)
{
printf( "%d\n", x );
}
int main()
{
void (*foo)(int);
/* the ampersand is actually optional */
foo = &my_int_func;
return 0;
}(Note: all examples are written to be compatible with both C and C++.)
Using a Function Pointer
To call the function pointed to by a function pointer, you treat the function pointer as though it were the name of the function you wish to call. The act of calling it performs the dereference; there’s no need to do it yourself:
#include <stdio.h>
void my_int_func(int x)
{
printf( "%d\n", x );
}
int main()
{
void (*foo)(int);
foo = &my_int_func;
/* call my_int_func (note that you do not need to write (*foo)(2) ) */
foo( 2 );
/* but if you want to, you may */
(*foo)( 2 );
return 0;
}Note that function pointer syntax is flexible; it can either look like most other uses of pointers, with & and *, or you may omit that part of syntax. This is similar to how arrays are treated, where a bare array decays to a pointer, but you may also prefix the array with & to request its address.
Function Pointers in the Wild
Let’s go back to the sorting example where I suggested using a function pointer to write a generic sorting routine where the exact order could be specified by the programmer calling the sorting function. It turns out that the C function qsort does just that.
From the Linux man pages, we have the following declaration for qsort (from stdlib.h):
void qsort(void *base, size_t nmemb, size_t size,
int(*compar)(const void *, const void *));Note the use of void*s to allow qsort to operate on any kind of data (in C++, you’d normally use templates for this task, but C++ also allows the use of void* pointers) because void* pointers can point to anything. Because we don’t know the size of the individual elements in a void* array, we must give qsort the number of elements, nmemb, of the array to be sorted, base, in addition to the standard requirement of giving the length, size, of the input.
But what we’re really interested in is the compar argument to qsort: it’s a function pointer that takes two void *s and returns an int. This allows anyone to specify how to sort the elements of the array base without having to write a specialized sorting algorithm. Note, also, that compar returns an int; the function pointed to should return -1 if the first argument is less than the second, 0 if they are equal, or 1 if the second is less than the first.
For instance, to sort an array of numbers in ascending order, we could write code like this:
#include <stdlib.h>
int int_sorter( const void *first_arg, const void *second_arg )
{
int first = *(int*)first_arg;
int second = *(int*)second_arg;
if ( first < second )
{
return -1;
}
else if ( first == second )
{
return 0;
}
else
{
return 1;
}
}
int main()
{
int array[10];
int i;
/* fill array */
for ( i = 0; i < 10; ++i )
{
array[ i ] = 10 - i;
}
qsort( array, 10 , sizeof( int ), int_sorter );
for ( i = 0; i < 10; ++i )
{
printf ( "%d\n" ,array[ i ] );
}
}Using Polymorphism and Virtual Functions Instead of Function Pointers (C++)
You can often avoid the need for explicit function pointers by using virtual functions. For instance, you could write a sorting routine that takes a pointer to a class that provides a virtual function called compare:
class Sorter
{
public:
virtual int compare (const void *first, const void *second);
};// cpp_qsort, a qsort using C++ features like virtual functions void cpp_qsort(void *base, size_t nmemb, size_t size, Sorter *compar);
inside cpp_qsort, whenever a comparison is needed, compar->compare should be called. For classes that override this virtual function, the sort routine will get the new behavior of that function. For instance:
class AscendSorter : public Sorter
{
virtual int compare (const void*, const void*)
{
int first = *(int*)first_arg;
int second = *(int*)second_arg;
if ( first < second )
{
return -1;
}
else if ( first == second )
{
return 0;
}
else
{
return 1;
}
}
};and then you could pass in a pointer to an instance of the AscendSorter to cpp_qsort to sort integers in ascending order.
But Are You Really Not Using Function Pointers?
Virtual functions are implemented behind the scenes using function pointers, so you really are using function pointers–it just happens that the compiler makes the work easier for you. Using polymorphism can be an appropriate strategy (for instance, it’s used by Java), but it does lead to the overhead of having to create an object rather than simply pass in a function pointer.
Function Pointers Summary
Syntax
Declaring
Declare a function pointer as though you were declaring a function, except with a name like *foo instead of just foo:
void (*foo)(int);Initializing
You can get the address of a function simply by naming it:
void foo();
func_pointer = foo;or by prefixing the name of the function with an ampersand:
void foo();
func_pointer = &foo;Invoking
Invoke the function pointed to just as if you were calling a function.
func_pointer( arg1, arg2 );or you may optionally dereference the function pointer before calling the function it points to:
(*func_pointer)( arg1, arg2 );Benefits of Function Pointers
- Function pointers provide a way of passing around instructions for how to do something
- You can write flexible functions and libraries that allow the programmer to choose behavior by passing function pointers as arguments
- This flexibility can also be achieved by using classes with virtual functions
Source :
reinterpret cast in C++
A reinterpret_cast operator handles conversions between unrelated types.
>>-reinterpret_cast--<--Type-->--(--expression--)--------------><
The reinterpret_cast operator produces a value of a new type that has the same bit pattern as its argument. You cannot cast away a const or volatile qualification. You can explicitly perform the following conversions:
- A pointer to any integral type large enough to hold it
- A value of integral or enumeration type to a pointer
- A pointer to a function to a pointer to a function of a different type
- A pointer to an object to a pointer to an object of a different type
- A pointer to a member to a pointer to a member of a different class or type, if the types of the members are both function types or object types
A null pointer value is converted to the null pointer value of the destination type.
Given an lvalue expression of type T and an object x, the following two conversions are synonymous:
- reinterpret_cast<T&>(x)
- *reinterpret_cast<T*>(&x)
// An example that uses reinterpret_cast.
#include <iostream>using namespace std;int main(){int i;char *p = "This is a string";i = reinterpret_cast<int> (p); // cast pointer to integercout << i;return 0;}
Here, reinterpret_cast converts the pointer p into an integer. This conversion represents a fundamental type change and is a good use of reinterpret_cast.
Source : Google
const cast in C++
A const_cast operator is used to add or remove a const or volatile modifier to or from a type.
>>-const_cast--<--Type-->--(--expression--)------------><
Type and the type of expression may only differ with respect to their const and volatile qualifiers. Their cast is resolved at compile time. A single const_cast expression may add or remove any number of const or volatile modifiers.
The result of a const_cast expression is an rvalue unless Type is a reference type. In this case, the result is an lvalue.
Types can not be defined within const_cast.
The following demonstrates the use of the const_cast operator:
#include <iostream>using namespace std;
void f(int* p) {cout << *p << endl;}
int main(void) {const int a = 10;const int* b = &a;
// Function f() expects int*, not const int*// f(b);int* c = const_cast<int*>(b);f(c);
// Lvalue is const// *b = 20;
// Undefined behavior// *c = 30;
int a1 = 40;const int* b1 = &a1;int* c1 = const_cast<int*>(b1);
// Integer a1, the object referred to by c1, has// not been declared const*c1 = 50;
return 0;}
The compiler will not allow the function call f(b). Function f() expects a pointer to an int, not a const int. The statement int* c = const_cast<int>(b) returns a pointer c that refers to a without the const qualification of a. This process of using const_cast to remove the const qualification of an object is called casting away constness. Consequently the compiler will allow the function call f(c).
The compiler would not allow the assignment *b = 20 because b points to an object of type const int. The compiler will allow the *c = 30, but the behavior of this statement is undefined. If you cast away the constness of an object that has been explicitly declared as const, and attempt to modify it, the results are undefined.
However, if you cast away the constness of an object that has not been explicitly declared as const, you can modify it safely. In the above example, the object referred to by b1 has not been declared const, but you cannot modify this object through b1. You may cast away the constness of b1 and modify the value to which it refers.
Source : Google
Static cast in C++
The static_cast operator performs a non-polymorphic cast.
It can be used for any standard conversion.
No run-time checks are performed.
The static_cast operator can be used for operations such as converting a pointer to a base class to a pointer to a derived class. Such conversions are not always safe.
In general you use static_cast when you want to convert numeric data types such as enums to ints or ints to floats, and you are certain of the data types involved in the conversion. static_cast conversions are not as safe as dynamic_cast conversions, because static_cast does no run-time type check, while dynamic_cast does. A dynamic_cast to an ambiguous pointer will fail, while a static_cast returns as if nothing were wrong; this can be dangerous. Although dynamic_cast conversions are safer, dynamic_cast only works on pointers or references, and the run-time type check is an overhead.
static_cast<type> (expr)
Here, type specifies the target type of the cast, and expr is the expression being cast into the new type.
The static_cast operator is essentially a substitute for the original cast operator. It simply performs a non-polymorphic cast.
For example, the following casts an int value into a double.
// Use static_cast.
#include <iostream>using namespace std;int main(){int i;for(i=0; i<10; i++)cout << static_cast<double> (i) / 3 << " ";return 0;}
Source : Google
Dynamic cast in C++
The dynamic_cast performs a run-time cast that verifies the validity of a cast. If the cast is invalid at the time dynamic_cast is executed, then the cast fails.
The general form of dynamic_cast is shown here:
dynamic_cast<target-type> (expr)
Here, target-type specifies the target type of the cast, and expr is the expression being cast into the new type. The target type must be a pointer or reference type, and the expression being cast must evaluate to a pointer or reference. Thus, dynamic_cast may be used to cast one type of pointer into another or one type of reference into another.
The purpose of dynamic_cast is to perform casts on polymorphic types.
For example, given two polymorphic classes B and D, with D derived from B, a dynamic_cast can always cast a D* pointer into a B* pointer. This is because a base pointer can always point to a derived object. But a dynamic_cast can also cast a B* pointer into a D* pointer only if the object being pointed to actually is a D object.
In general, dynamic_cast will succeed if the pointer (or reference) being cast is a pointer (or reference) to either an object of the target type or an object derived from the target type. Otherwise, the cast will fail. If the cast fails, then dynamic_cast evaluates to null if the cast involves pointers. If a dynamic_cast on reference types fails, a bad_cast exception is thrown.
Here is a simple example. Assume that Base is a polymorphic class and that Derived is derived from Base.
Base *bp, b_ob;Derived *dp, d_ob;bp = &d_ob; // base pointer points to Derived objectdp = dynamic_cast<Derived *> (bp); // cast to derived pointer OKif(dp) cout << "Cast OK";
Here, the cast from the base pointer bp to the derived pointer dp works because bp is actually pointing to a Derived object. Thus, this fragment displays Cast OK. But in the next fragment, the cast fails because bp is pointing to a Base object and it is illegal to cast a base object into a derived object.
bp = &b_ob; // base pointer points to Base objectdp = dynamic_cast<Derived *> (bp); // errorif(!dp) cout << "Cast Fails";
Demonstration:
#include<iostream>using namespace std;
struct B { virtual ~B() { } };struct D : public B { };
int main() {
B *bptr, bobj;D *dptr, dobj;
cout<<"base pointer points to derived object \n";
bptr = &dobj;//base pointer points to derived object
cout<<"addr of dobj="<<&dobj<<"\n";cout<<"bptr="<<bptr<<"\n";
dptr = dynamic_cast<D *>(bptr);
if(dptr){ cout<<"Cast ok \n";cout<<"dptr="<<dptr<<"\n";}elsecout<<"Cast fails";
cout<<"\n";
cout<<"derived pointer points to base object \n";
bptr = &bobj;dptr = dynamic_cast<D *>(bptr);
if(dptr)cout<<"Cast ok.";elsecout<<"Cast fails \n";cout<<"dptr="<<dptr<<"\n";getchar();return 0;}
Output:
base pointer points to derived objectaddr of dobj=0x22ff20bptr=0x22ff20Cast okdptr=0x22ff20
derived pointer points to base objectCast failsdptr=0
Source : Google
RTTI
Run-Time Type Identification (RTTI)
Run-time type information may be new to you because it is not found in non-polymorphic languages, such as C. In non-polymorphic languages there is no need for run-time type information because the type of each object is known at compile time (i.e., when the program is written). However, in polymorphic languages such as C++, there can be situations in which the type of an object is unknown at compile time because the precise nature of that object is not determined until the program is executed. C++ implements polymorphism through the use of class hierarchies, virtual functions, and base-class pointers. Since base-class pointers may be used to point to objects of the base class or any object derived from that base, it is not always possible to know in advance what type of object will be pointed to by a base pointer at any given moment in time. This determination must be made at run time, using run-time type identification.
Note : A class that declares or inherits a virtual function is called a polymorphic class.
typeid
To obtain an object's type, use typeid.
You must include the header <typeinfo> in order to use typeid.
Its most commonly used form is shown here:
typeid(object)
Here, object is the object whose type you will be obtaining. It may be of any type, including the built-in types and class types that you create.
typeid returns a reference to an object of type type_info that describes the type of object.
The type_info class defines the following public members:
bool operator==(const type_info &ob);bool operator!=(const type_info &ob);bool before(const type_info &ob);const char *name( );
The overloaded == and != provide for the comparison of types. The before() function returns true if the invoking object is before the object used as a parameter in collation order(This function is mostly for internal use only. Its return value has nothing to do with inheritance or class hierarchies) The name() function returns a pointer to the name of the type.
The most important use of typeid occurs when it is applied through a pointer of a polymorphic base class. In this case, it will automatically return the type of the actual object being pointed to, which may be a base-class object or an object derived from that base. (Remember, a base-class pointer can point to objects of the base class or of any class derived from that base.) Thus, using typeid, you can determine at run time the type of the object that is being pointed to by a base-class pointer.
The following program demonstrates this principle.
// An example that uses typeid on a polymorphic class hierarchy.
#include <iostream>#include <typeinfo>using namespace std;
class Mammal {public:virtual bool lays_eggs() { return false; } // Mammal is polymorphic class// ...};
class Cat: public Mammal {public:// ...};
class Platypus: public Mammal {public:bool lays_eggs() { return true; }// ...};
int main(){Mammal *p, AnyMammal;Cat cat;Platypus platypus;
p = &AnyMammal;cout << "p is pointing to an object of type ";cout << typeid(*p).name() << endl;
p = &cat;cout << "p is pointing to an object of type ";cout << typeid(*p).name() << endl;
p = &platypus;cout << "p is pointing to an object of type ";cout << typeid(*p).name() << endl;
return 0;}
The output produced by this program is shown here:
p is pointing to an object of type class Mammalp is pointing to an object of type class Catp is pointing to an object of type class Platypus
As explained, when typeid is applied to a base-class pointer of a polymorphic type, the type of object pointed to will be determined at run time, as shown by the output produced by the program. In all cases, when typeid is applied to a pointer of a nonpolymorphic class hierarchy, then the base type of the pointer is obtained. That is, no determination of what that pointer is actually pointing to is made.
For example, comment out the virtual keyword before the function lays_eggs() in Mammal and then compile and run the program.
You will see the following output.
p is pointing to an object of type class Mammalp is pointing to an object of type class Mammalp is pointing to an object of type class Mammal
Since Mammal is no longer a polymorphic class, the type of each object will be Mammal because that is the type of the pointer.
Since typeid is commonly applied to a dereferenced pointer (i.e., one to which the *operator has been applied), a special exception has been created to handle the situation in which the pointer being dereferenced is null. In this case, typeid throws bad_typeid.
References to an object of a polymorphic class hierarchy work the same as pointers. When typeid is applied to a reference to an object of a polymorphic class, it will return the type of the object actually being referred to, which may be of a derived type. The circumstance where you will most often make use of this feature is when objects are passed to functions by reference.
For example, in the following program,
the function WhatMammal() declares a reference parameter to objects of type Mammal. This means that WhatMammal() can be passed references to objects of type Mammal or any class derived from Mammal. When the typeid operator is applied to this parameter, it returns the actual type of the object being passed.
// Use a reference with typeid.
#include <iostream>#include <typeinfo>using namespace std;
class Mammal {public:virtual bool lays_eggs() { return false; }// Mammal is polymorphic// ...};
class Cat: public Mammal {public:// ...};
class Platypus: public Mammal {public:bool lays_eggs() { return true; }// ...};
// Demonstrate typeid with a reference parameter.void WhatMammal(Mammal &ob){cout << "ob is referencing an object of type ";cout << typeid(ob).name() << endl;}
int main(){Mammal AnyMammal;Cat cat;Platypus platypus;WhatMammal(AnyMammal);WhatMammal(cat);WhatMammal(platypus);return 0;}
The output produced by this program is shown here:
ob is referencing an object of type class Mammalob is referencing an object of type class Catob is referencing an object of type class Platypus
There is a second form of typeid that takes a type name as its argument. This form is shown here:
typeid(type-name)
For example, the following statement is perfectly acceptable:
cout << typeid(int).name();
The main use of this form of typeid is to obtain a type_info object that describes the specified type so that it can be used in a type comparison statement. For example, this form of WhatMammal() reports that cats don't like water:
void WhatMammal(Mammal &ob){cout << "ob is referencing an object of type ";cout << typeid(ob).name() << endl;if(typeid(ob) == typeid(Cat))cout << "Cats don't like water.\n";}
