More Effective C ++ Terms 2

zhaozj2021-02-08  294

Terms 2: Try to use C style type conversion

Think about the typing type conversion function (CAST) in the program design, it is as despise like a GOTO statement. But it is still not unbearable, because when certain critical junctions, type conversion is still required, then it is a necessity.

However, the type conversion of the C style does not represent all type conversion functions. They are too rude, allowing you to convert between any types. But if you want to make more accurate type conversion, this will be an advantage. There is a huge difference in these types of conversion, such as converting a pointer-to-const-object pointing to the Const object into pointer to a non-Const object (ie one Only the type conversion of COSNT is removed, and a pointer to the base class is converted into a pointer to the subclass (ie, completely changing the object type). Traditional C style type conversion does not distinguish between the two conversions. (This is not surprising, because the type of C style is designed for C language, not for C language).

The type of C-style is difficult to identify in the program statement. Conversion of types of syntax consists of parentheses and identifiers, and these can be used anywhere in C . This makes it difficult to answer the problem like this about type conversion, "Is it using type conversion in this program?". This is because manual reading is likely to ignore the type of conversion statement, and use the toolplicer like GREP to distinguish them from statements.

C overcome the disadvantages of C style type conversion by introducing four new type conversion operators, these four operators are, static_cast, const_cast, dynamic_cast, and reinterpret_cast. In most cases, you only need to know that you are used to writing, for these operators.

(TYPE) Expression

And now you should always write this:

Static_cast (expression)

For example, suppose you want to convert an int to Double so that the expression containing the INT type variable produces a floating point value. If you use C style, you can write this:

INT firstnumber, secondnumber;

...

Double result = (Double) firstnumber / secondnumber;

If you use the above new type conversion method, you should write this:

Double Result = static_cast (firstnumber) / secondnumber;

Such type conversions are easily identified regardless of manual or for procedures.

STATIC_CAST is basically as strong as powerful and meaningful in functionality, meaning. It also has functions. For example, you can't use Static_CAST icon to convert Struct into an int type or convert the double type to a pointer type like a type of C style, and Static_CAST cannot remove the const attribute from the expression because another new type of conversion operator Const_cast has such a function.

Other new C type conversion operators are used in a place where more restrictions are needed. Const_cast is used to convert the const or volatileness attribute that transitions the expression. By using const_cast, you emphasize you and the compiler that you want to do through the type conversion just change some of the constness or volatileness attributes. This meaning is constrained by the compiler. If you try to use const_cast to complete something other than the Constness or VolatileAss property, your type conversion will be rejected. Here are some examples: Class Widget {...};

Class SpecialWidget: Public Widget {...};

Void Update (SpecialWidget * PSW);

SpecialWidget SW; // SW is a non-Const object.

Const SpecialWidget & CSW = SW; // CSW is a reference to SW

// It is a const object

Update (& CSW); // Error! Unable to pass a const SpecialWidget * variable

/ / Give a function that handles SpecialWidget * type variables

Update (const_cast );

/ / Correct, CSW's ConST is converted down (

// CSW and SW two variables in Update

// Can be updated in the function)

Update ((SpecialWidget *) & CSW);

//, but use a more difficult to identify

// 's type conversion

Widget * pw = new specialwidget;

Update (PW); // Error! The type of PW is widget *, but

// update function processed a specialWidget * type

Update (const_cast (pw));

// Error! Const_cast can only be used

// Constness or Volatileness is placed. ,

// cannot be used to transition to the inheritance subclass.

So far, const_cast's most common use is to convert the const attribute of the object.

The second special type converter is Dynamic_cast, which is used to convert downwardly along the inheritance relationship of the class. That is to say, you can use Dynamic_CAST to convert pointers or references to the base class to point to its derived class or its brothers, and you can know if the conversion is successful. Failed conversions will return an empty pointer (when the pointer is converted) or throw an exception (when the reference is converted):

Widget * PW;

...

Update (Dynamic_cast (PW));

/ / Correct, pass it to the UPDATE function a pointer

/ / Tong points to PM of the PW of the variable type specialwidget

// If PW does point to an object,

/ / Otherwise, pass the past will make the empty pointer.

Void UpdateViaref (SpecialWidget & RSW);

Updateviaaref (Dynamic_cast (* Pw));

//correct. Pass to the UpdateviaRef function

// SpecialWidget PW pointer if pw

/ / I really point to an object

/ / Otherwise it will throw an abnormality

Dynamic_casts is restricted in helping you browse inheritance levels. It cannot be used to lack the type of virtual function (see Terms 24), and you cannot use it to convert Constness: int firstnumber, secondnumber;

...

Double Result = Dynamic_cast (firstnumber) / secondnumber;

// Error! No inheritance

Const Specialwidget Sw;

...

Update (Dynamic_cast );

// Error! Dynamic_cast can not be converted

/ / Drop const.

If you want to convert in type without inheritance, you may think static_cast. If you are in order to remove const, you have to use const_cast.

The last one in these four types of converters is ReinterPret_cast. This operator is used for the transition result of the type conversion of this operator to be implemented as an Implementation-Defined. Therefore, it is difficult to transplant using ReinterPret_Casts.

The most common use of ReinterPret_casts is to convert between the function pointer type. For example, suppose you have a function pointer array:

TypeDef void (* funcptr) (); // Funcptr is a pointing function

// The pointer does not have a parameter

// Also return value type is Void

Funcptr Funcptrarray [10]; // Funcptrarray is a capacity

// 10 arrays of 10 FuncPTRS pointers

Let us assume that you want (because some inexplicable reasons) put a pointer to the following functions into the FuncPtrarray array:

INT DOSMETHING ();

You can't do it directly without type conversion, because the DOSMETHING function has an error type for the Funcptraray array. The function return value in the FuncptraRray array is a Void type, and the DOSMETHING function return value is an int type.

Funcptrarray [0] = & dosomething; // Error! Type does not match

Reinterpret_cast allows you to force the compiler to see them with your method:

Funcptrarray [0] = // this compiles

Reinterpret_cast (& DOSMETHING);

The code of the conversion function pointer is unmiglable (C does not guarantee that all function pointers are represented by the same method), in some cases such conversion generate incorrect results (see Terms 31), so you should avoid conversion Function pointer type unless you are in a critical moment with a warhead and sharp knife throat. A sharp knife. A very sharp knife.

If you use the compiler lack support for new type conversion methods, you can use traditional type conversion methods to replace Static_cast, const_cast, and reinterpret_cast. You can also use the following macro to simulate the new type of conversion syntax:

#define static_cast (Type, EXPR) ((Type) (EXPR))

#define const_cast (type, expr) ((type) (tPR))

#define reinterpret_cast (type, expr) ((Type) (EXPR))

You can use it like this:

Double Result = static_cast (double, firstnumber) / secondnumber; update (const_cast (specialwidget *, & sw));

Funcptrarray [0] = Reinterpret_cast (Funcptr, & Dosomething);

These analog will not be as safe as a real operator, but when your compiler can support new types of transitions, they simplify the process of upgrading the code.

There is no easy way to simulate the operation of Dynamic_cast, but many of the libraries provide functions that are securely converted between derived classes and base classes. If you don't have these functions and you have to make such a type of conversion, you can also return to the type conversion method of the C style, but you will not know if the type conversion failed. Of course, you can also define a macro to simulate the functionality of Dynamic_cast, just like simulating other types of conversion:

#define Dynamic_cast (Type, EXPR) (Type) (EXPR)

Keep in mind that this simulation does not fully realize the functionality of Dynamic_cast, it doesn't matter to know if the conversion failed.

I know, yes, I know that new type conversion operators are not very beautiful and it is very troublesome to type with keyboards. If you find that they seem to be annoying, the type of C-style can continue to use and legal. However, it is because the new type of converter lacks beauty to make it make up for the disadvantages of meaning accuracy and recognition, and programs that use the new type of converter are more likely to be parsed (whether it is for artificial or tool programs) They allow the compiler to detect errors that cannot be found. These are strong reasons for giving up the C style type conversion method, as well as a third reason: perhaps the type of converter is not beautiful and typing trouble is a good thing.

转载请注明原文地址:https://www.9cbs.com/read-964.html

New Post(0)