| | |
casting
Thread Solved
![]() |
Should I avoid casting between data types?
I haven't really seen much about the use of this, but it seems like one of those last-minute-no-way-around kind of methods... but, for example, how would I use the length of a string in a for loop? The length property of a string is size_t, and if I had an integer i in a loop, how could I do that?
Where would casting be useful? Where should I avoid it? What are other methods of dealing with different data types that are better than cast?
I haven't really seen much about the use of this, but it seems like one of those last-minute-no-way-around kind of methods... but, for example, how would I use the length of a string in a for loop? The length property of a string is size_t, and if I had an integer i in a loop, how could I do that?
Where would casting be useful? Where should I avoid it? What are other methods of dealing with different data types that are better than cast?
I wake up! And my mind's out, never again will I sell out. Converting vegetarians.
Into the midnight giving it to you, I don't know it just feels right.
This is the time of the revolution, Cooking the next step.
Converting vegetarians, minding the gap since 1996
Into the midnight giving it to you, I don't know it just feels right.
This is the time of the revolution, Cooking the next step.
Converting vegetarians, minding the gap since 1996
First, the compiler will provide a warning (not error. Warnings are not fatal) for not casting between int and size_t... but there is no harm in doing either
for (int i=0; i <(int)somestring.length(); i++) or for (size_t i=0; i < somestring.length(); i++) {. There is nothing wrong with casting... but you need to understand the implications in so doing.... what happens if you cast a float to an int? What about an int to a float? Is upcasting an inheritance tree ok? Just out of curiosity, if you didn't have casts, how could you make use of a void pointer? My point here, is that casting has very valid and useful purposes, but you must absolutely know what happens to the data when you do it. •
•
Join Date: Aug 2008
Posts: 206
Reputation:
Solved Threads: 31
As a general rule, yes you should.
An implicit conversion exists between int and size_t so, in rough terms, you shouldn't need an explicit conversion between them.
Note "explicit conversion" is actually the more correct name for a "cast".
In practice, the conversion can lose information (signed to unsigned, and different variable sizes), so several compilers will emit a warning when doing that conversion. If (and I repeat if) you know that conversion is valid, you can safely ignore the warning messages. If you can't tolerate warning messages from compilers, then an explicit conversion generally has the side effect of stopping the compiler complaining. That has the disadvantage that it also stops the compiler from emitting complaints that you should really address properly.
However, if you can guarantee the conversion is safe (i.e. you know that the value of the size_t variable can be stored in an int) a technique is;
Explicit conversions are useful when you know a conversion is safe and the compiler considers the conversion erroneous (i.e. it emits and error message and refuses to continue) or suspicious (i.e. it emits a warning message, even if continues to compile).
An example is that, in C++, it is necessary to convert the return from malloc() to a pointer of an appropriate type. While it is usually better to employ operator new instead, an explicit conversion can be a simpler way. The flip side of this conversion is that it can also be used to permit an invalid conversion: for example, the return from malloc() shouild never be converted to a pointer to a non-POD class (in rough terms, a non-POD class is a class that has declared constructors, assignment operators,a destructor, or any virtual function).
An explicit conversion is also useful - rarely - to resolve ambiguity. Such ambiguity can occur with C++ classes that supply multiple conversion operations. [The better strategy is to ensure that no class supports multiple conversions].
As I said above, you should avoid it whenever possible. Where practical, an alternative should be found. The explicit conversion needs to be viewed as an absolute last resort.
Generally, it comes down to design.
Instead of using the C malloc() function, use C++'s operator new.
Avoid writing classes that support multiple conversion operations (eg operator SomeType() members). Instead, write functions that the programmer must explicitly call to do the required (and intended) conversion. This is the reason, for example, that std::string supports the c_str() member function and does not support a direct conversion to (const char *).
In C++, make use of the _cast<> operators (const_cast, static_cast, dynamic_cast, reinterpret_cast) if you really have to, and avoid the C-style cast. And avoid using the _cast<> operators as well, if at all practical.
As a rough rule, you should never need to perform an explicit conversion from a base class to a derived class (or conversion of such pointers or references). The need to do this can, almost always, be eliminated by careful class design. For example, the base class probably needs to be polymorphic (i.e. provide virtual functions that can be over-ridden by the derived classes).
•
•
•
•
I haven't really seen much about the use of this, but it seems like one of those last-minute-no-way-around kind of methods... but, for example, how would I use the length of a string in a for loop? The length property of a string is size_t, and if I had an integer i in a loop, how could I do that?
Note "explicit conversion" is actually the more correct name for a "cast".
In practice, the conversion can lose information (signed to unsigned, and different variable sizes), so several compilers will emit a warning when doing that conversion. If (and I repeat if) you know that conversion is valid, you can safely ignore the warning messages. If you can't tolerate warning messages from compilers, then an explicit conversion generally has the side effect of stopping the compiler complaining. That has the disadvantage that it also stops the compiler from emitting complaints that you should really address properly.
However, if you can guarantee the conversion is safe (i.e. you know that the value of the size_t variable can be stored in an int) a technique is;
C++ Syntax (Toggle Plain Text)
size_t end = whatever(); for (int i = 0; i < (int)end; ++i) loop_body();
An example is that, in C++, it is necessary to convert the return from malloc() to a pointer of an appropriate type. While it is usually better to employ operator new instead, an explicit conversion can be a simpler way. The flip side of this conversion is that it can also be used to permit an invalid conversion: for example, the return from malloc() shouild never be converted to a pointer to a non-POD class (in rough terms, a non-POD class is a class that has declared constructors, assignment operators,a destructor, or any virtual function).
An explicit conversion is also useful - rarely - to resolve ambiguity. Such ambiguity can occur with C++ classes that supply multiple conversion operations. [The better strategy is to ensure that no class supports multiple conversions].
As I said above, you should avoid it whenever possible. Where practical, an alternative should be found. The explicit conversion needs to be viewed as an absolute last resort.
•
•
•
•
What are other methods of dealing with different data types that are better than cast?
Instead of using the C malloc() function, use C++'s operator new.
Avoid writing classes that support multiple conversion operations (eg operator SomeType() members). Instead, write functions that the programmer must explicitly call to do the required (and intended) conversion. This is the reason, for example, that std::string supports the c_str() member function and does not support a direct conversion to (const char *).
In C++, make use of the _cast<> operators (const_cast, static_cast, dynamic_cast, reinterpret_cast) if you really have to, and avoid the C-style cast. And avoid using the _cast<> operators as well, if at all practical.
As a rough rule, you should never need to perform an explicit conversion from a base class to a derived class (or conversion of such pointers or references). The need to do this can, almost always, be eliminated by careful class design. For example, the base class probably needs to be polymorphic (i.e. provide virtual functions that can be over-ridden by the derived classes).
Last edited by grumpier; Jan 11th, 2009 at 9:12 pm.
what's the difference between an explicit conversion and an implicit conversion?
By what means can a class "Support" a direct conversion? Does this mean I couldn't go
I think what I'm asking is (I'm just trying to understand how data-types work in C++) if I wrote a class, how would I deal with what it can and can't be converted to?
Also, what does string::c_str() do? Is it just a function that returns a const char*?
Thanks for your help so far btw... I'm starting to understand a lot more about this
oh, what WOULD happen if you casted a float to an int? Just lose the decimal places? Or a signed to unsigned or vice versa?
By what means can a class "Support" a direct conversion? Does this mean I couldn't go
if(a string==a char*){ , but I could still cast it? or could I cast it?I think what I'm asking is (I'm just trying to understand how data-types work in C++) if I wrote a class, how would I deal with what it can and can't be converted to?
Also, what does string::c_str() do? Is it just a function that returns a const char*?
Thanks for your help so far btw... I'm starting to understand a lot more about this
oh, what WOULD happen if you casted a float to an int? Just lose the decimal places? Or a signed to unsigned or vice versa?
I wake up! And my mind's out, never again will I sell out. Converting vegetarians.
Into the midnight giving it to you, I don't know it just feels right.
This is the time of the revolution, Cooking the next step.
Converting vegetarians, minding the gap since 1996
Into the midnight giving it to you, I don't know it just feels right.
This is the time of the revolution, Cooking the next step.
Converting vegetarians, minding the gap since 1996
•
•
Join Date: Aug 2008
Posts: 206
Reputation:
Solved Threads: 31
An explicit conversion is what you're calling a cast. An implicit conversion is a conversion between types that the compiler allows or performs, even if you don't do a cast. For example;
The initialisation of j involves an implicit conversion of an int to a long. The compiler knows how to do that, so it happens implicitly (as far as the programmer is concerned).
Conversion between basic types are built in: for example, the compiler knows how to add an int to a double.
Class types support conversions in two ways: by the constructors they supply, and by operator functions.
allows a const char pointer to be converted to an X. Given a function;
the call
will create a temporary X by passing "Hello" to its constructor, and then pass that temporary to func(). That process of creating the temporary X from "Hello" is a conversion.
The other way is that;
declares an operator that allows a Y to be converted to a const char *. So, given;
it is possible to do this;
as the compiler will implicitly invoke the operator const char *() for the object y, and pass the result to another_func().
Because of all that, you control the conversions supported by a class by controlling what constructors it supports and what conversion operators it supports. Constructors can be used to do conversions. However, prefixing the constructor keyword to the constructor declaration prevents it from being used to do implicit conversions (and some other things).
std::string::c_str() returns a const char *. However, std::string does not supply an operator const char *().
Converting a float to an int rounds towards zero. That involves dropping the decimal places for small values. However, that doesn't work for larger values. For example, assume your compiler supports a 32 bit float and a 32 bit int (fairly commonly true). The float can represent the value 3.4E+30. What would you expect to happen if you convert that value to an int (which can only hold values in the range -2,147,483,648 to 2,147,483,647)?
C++ Syntax (Toggle Plain Text)
int i = 3; long j = i;
Conversion between basic types are built in: for example, the compiler knows how to add an int to a double.
Class types support conversions in two ways: by the constructors they supply, and by operator functions.
C++ Syntax (Toggle Plain Text)
class X { public: X(const char *); };
C++ Syntax (Toggle Plain Text)
void func(const X &);
C++ Syntax (Toggle Plain Text)
func("Hello");
The other way is that;
C++ Syntax (Toggle Plain Text)
class Y { public: operator const char *() const; // conversion to const char * };
C++ Syntax (Toggle Plain Text)
void another_func(const char *);
C++ Syntax (Toggle Plain Text)
Y y; / assume we have a default constructor another_func(y);
Because of all that, you control the conversions supported by a class by controlling what constructors it supports and what conversion operators it supports. Constructors can be used to do conversions. However, prefixing the constructor keyword to the constructor declaration prevents it from being used to do implicit conversions (and some other things).
std::string::c_str() returns a const char *. However, std::string does not supply an operator const char *().
Converting a float to an int rounds towards zero. That involves dropping the decimal places for small values. However, that doesn't work for larger values. For example, assume your compiler supports a 32 bit float and a 32 bit int (fairly commonly true). The float can represent the value 3.4E+30. What would you expect to happen if you convert that value to an int (which can only hold values in the range -2,147,483,648 to 2,147,483,647)?
Last edited by grumpier; Jan 11th, 2009 at 10:50 pm.
![]() |
Similar Threads
- Type casting and type conversions (C)
- Type casting (C++)
- Problems casting a const char* to char* (C++)
- type casting (C++)
- casting error (Java)
Other Threads in the C++ Forum
- Previous Thread: does debug symbols in code slowdown program
- Next Thread: How to adjust class objects through seperate class functions???
| Thread Tools | Search this Thread |
api array based binary bitmap c++ c/c++ char class classes code coding compaitibility compile console conversion count delete deploy desktop developer directshow dll download dynamic dynamiccharacterarray email encryption error factorial file floatingpoint forms fstream function functions game givemetehcodez graph guessing gui homeworkhelp homeworkhelper iamthwee ifstream input int integer java lib linkedlist linker loop looping loops map math matrix maze memory multiple net news node oop output parameter payment pointer problem program programming project projectassignmenthelp protection python random rank read recursion reference rpg skills string strings temperature template test text text-file tree url variable vector video win32 windows winsock wordfrequency wxwidgets






