Best practice in C++ for casting between number types [duplicate]

混江龙づ霸主 提交于 2019-12-10 01:36:56

问题


What is the best practice for casting between the different number types? Types float, double, int are the ones I use the most in C++.

An example of the options where f is a float and n is a double or an int:

float f = static_cast<float>(n);
float f = float(n);
float f = (float)n;

I usually write static_cast<T>(...) but wondered if there was any consensus within the C++ development community if there is a preferred way.

I appreciate this is may end up being an opinion based question and there may not be a "standard" way, in which case please let me know that there is no standard way so at least I know that :-)

I know this question has cropped up in relation to casting in general, however, I am interested specifically in numbers and whether there are specific best practices in the approach for number types.


回答1:


Just use static_cast. The problem with C casts is the ambiguity of the operation (i.e. point (1) of Explicit type conversion).

C++ casts avoid this. Additionally C++ casts are more visible when searching for them.

Using Stroustrup's words (What good is static_cast?):

Even an innocent-looking cast can become a serious problem if, during development or maintenance, one of the types involved is changed. For example, what does this mean?:

  x = (T)y;

We don't know. It depends on the type T and the types of x and y. T could be the name of a class, a typedef, or maybe a template parameter. Maybe x and y are scalar variables and (T) represents a value conversion. Maybe x is of a class derived from y's class and (T) is a downcast. Maybe x and y are unrelated pointer types. Because the C-style cast (T) can be used to express many logically different operations, the compiler has only the barest chance to catch misuses. For the same reason, a programmer may not know exactly what a cast does. This is sometimes considered an advantage by novice programmers and is a source of subtle errors when the novice guessed wrong.

The "new-style casts" were introduced to give programmers a chance to state their intentions more clearly and for the compiler to catch more errors.

[CUT]

A secondary reason for introducing the new-style cast was that C-style casts are very hard to spot in a program. For example, you can't conveniently search for casts using an ordinary editor or word processor.

[CUT]

casts really are mostly avoidable in modern C++

Also consider boost::numeric::converter / boost::numeric_cast that are safer alternatives (part of Boost.NumericConversion library).

E.g.

#include <iostream>
#include <boost/numeric/conversion/cast.hpp>

int main()
{
  using boost::numeric_cast;

  using boost::numeric::bad_numeric_cast;
  using boost::numeric::positive_overflow;
  using boost::numeric::negative_overflow;

  try
  {
    int i = 42;
    short s = numeric_cast<short>(i); // This conversion succeeds (is in range)
  }
  catch(negative_overflow &e)  { std::cout << e.what(); }
  catch(positive_overflow &e)  { std::cout << e.what(); }

  return 0;
}

In general for both implicit conversions and explicit conversions (through static_cast) the lack of preservation of range makes conversions between numeric types error prone.

numeric_cast detects loss of range when a numeric type is converted and throws an exception if the range cannot be preserved.




回答2:


Generally, these casting operators are classified under two major groups: specific casting operators and traditional casting operators. cplusplus.com explains it like this:

...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.

While working on a task, we (nearly) all use specific casting. After considering the advises, it's up to you somehow.

See the resource.



来源:https://stackoverflow.com/questions/37497016/best-practice-in-c-for-casting-between-number-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!