
Posted by Raju Bendalam on June 09, 201 at 00:21:26:
In Reply to: Re: Casting in C++ posted by Steve Lieu on December 08, 1999 at 14:03:34:
: Casting in C++
: The new C++ standard is full of powerful additions to the language: templates, run-time type identification (RTTI), namespaces, and exceptions. I will discuss one of the minor extensions: the new C++ casting operators. The new C++ cast operators enable you to develop programs that are easier to maintain, understand, and perform some conversions safely. Casts are used to convert the type of an object, expression, function argument, or return value to that of another type. Some conversions are performed automatically by the compiler without intervention by the programmer. These conversions are called implicit conversions. The standard C++ conversions and user-defined conversions are performed implicitly by the compiler where needed. Other conversions must be explicitly specified by the programmer are appropriately called explicit conversions.
:
: The C++ draft standard includes the following four casting operators:
: static_cast
: const_cast
: dynamic_cast, and
: reinterpret_cast
:
: The new C++ cast operators enable you to develop programs that are easier to maintain, understand, and also perform some conversions safely. Casts are used to convert the type of an object, expression, function argument, or return value to that of another type. Some conversions are performed automatically by the compiler without intervention by the programmer. These conversions are called implicit conversions. The standard C++ conversions and user-defined conversions are performed implicitly by the compiler where needed. Other conversions that must be explicitly specified by the programmer are appropriately called explicit conversions.
: The static_cast Operator
: The static_cast operator takes the form
: static_cast : to convert the expression expr to type T. Subject to certain restrictions, you may use static_cast to convert a base class pointer to a derived class pointer, perform arithmetic conversions, convert an int : More generally a static_cast may be used to perform the explicit inverse of the implicit standard conversions. A conversion from type S to T can only be done if : One of the more common uses of static_cast is to perform arithmetic conversions, such as from int to double. For example, to avoid the truncation in the : int total = 500; : We can write: : double rate = : A static_cast may also be used to convert an integral type to an enumeration. Consider: : enum fruit {apple=0,orange,banana}; : You may also use static_cast to convert any expression to a void in which case the value of the expression is discarded. : The const_cast operator takes the form : const_cast : and is used to add or remove the ``const-ness'' or ``volatile-ness'' from a type. : For example, a function, f, which takes a non-const argument: : double f( double& d ); : However, we want to call f from another function g: : void g (const double& d) : Since d, which is const and should not be modified, the compiler will complain because f may potentially modify its value. To get around this problem, we can use : void g (const double& d) : which strips away the ``const-ness'' of d before passing it to f. : Another scenario where const_cast is useful is inside const functions. Remember that when you make a member function const, you are telling your users (and the compiler) that calling this function will not change the value of the object. However, in some cases, we find that it is sometimes still necessary to change the value of some internal data members inside a function that is const. For example, take a good look at class B: : class B : Suppose that, f(), which is declared to be const, must modify _count whenever it is called: : void B::f() const : Every non-static member function of a class C has a this pointer. For non const member functions of class C, this has type : C * const : This means that this is a constant pointer. In other words, you cannot change what the pointer this points to, after all, that would be disastrous, wouldn't it? : For const member functions of class C, this has a type of : const C * const : Not only is this a constant pointer but also what is pointed to is constant. So the data members of C may not be changed through the this pointer. This is how the compiler ensures that you do not modify data members inside const functions. : Examining the member function B::f again, the statement _count is actually interpreted as this->_count. But since this has type const B * const, it cannot : We can, however, use const_cast to cast away the ``const-ness'' of this: : void B::f() const : Actually, you should not be casting away the ``const-ness'' of this using const_cast. C++ now has the keyword mutable for those data members whose value may be changed by const functions. By declaring _count as: : mutable int _count; : We can use the original implementation of B::f without casting away the ``const-ness'' of this. : The dynamic_cast operator takes the form : dynamic_cast : and can be used only for pointer or reference types to navigate a class hierarchy. The dynamic_cast operator can be used to cast from a derived class pointer to a : The dynamic_cast operator is actually part of C++'s run-time type information or RTTI sub-system. It has been provided for use with polymorphic classes - those classes which have at least one virtual function. Use static_cast to perform conversions between non-polymorphic classes. : All of the derived to base conversions are performed using the static type information. These conversions may, therefore, be performed on both non-polymorphic and polymorphic types. These conversions will produce the same result if they are converted using a static_cast. These conversions are fairly straightforward so we won't discuss them further. : Conversions down the hierarchy from base to derived or across a class hierarchy rely on run-time type information and can only be performed on polymorphic types. Such conversions can now be performed safely since dynamic_cast will indicate whether the conversion is successful. When performing a dynamic_cast on a pointer, a null pointer is returned when the cast is unsuccessful. When a reference is being cast, a Bad_cast exception is thrown. : We can use a dynamic_cast instead to check that the cast was successful: : void f (BankAcct* acct) : : : The reinterpret_cast operator is in this format. : reinterpret_cast : and is used to perform conversions between two unrelated types. The result of the conversion is usually implementation dependent and, therefore, not likely to be portable. You should use this type of cast only when absolutely necessary. A reinterpret_cast can also be used to convert a pointer to an integral type. If the integral type is then converted back to the same pointer type, the result will be the same value as the original pointer.
: to an enum, convert a reference of type X& to another reference of type Y&, convert an object of type X to an object of type Y, and convert a pointer-to-member to
: another pointer-to-member within the same class hierarchy.
: the conversion from type T to S is an implicit conversion. Also, the ``const-ness'' of the original type, S, must be preserved. You cannot use static_cast to
: change ``const-ness''; you must use const_cast instead.
: following computation:
: int days = 9;
: double rate = total/days;
: static_cast
: int i 1 = 2;
: fruit f1 = static_cast
: The const_cast Operator
: {
: val = f(d);
: }
: a const_cast:
: {
: val = f(const_cast
: }
: {
: public:
: B() {}
: ~B() {}
: void f() const;
: private:
: int _count;
: };
: {
: _count += 1;
: }
: However, you can still change what ever this points to (i.e., you can change data members of class C).
: be used to change the value of _count so the compiler reports an error.
: {
: B* const localThis =
: const_cast(this);
: localThis->_count += 1;
: }
: const_cast can also be used to strip away the ``volatile-ness'' of an object in a similar manner. You cannot use const_cast for any other types of casts, such as casting a base class pointer to a derived class pointer. If you do so the compiler will report an error.
: The dynamic_cast Operator
: base class pointer, cast a derived class pointer to another derived class pointer, or cast a base class pointer to a derived class pointer. Each of these conversions may also be applied to references. In addition, any pointer may also be cast to a void*.
: {
: SavingsAcct* d1 =
: dynamic_cast
: if (d1)
: {
: // d1 is a savings account
: }
: }
: When a pointer is converted to a void*, the resulting object points to the most derived object in the class hierarchy. This enables the object to be seen as raw memory.
: The reinterpret_cast Operator
Post a Follow Up: