Force transformation

xiaoxiao2021-03-06  40

Forcing four types of mandatory transformation may often be ignored as me, but sometimes it is more useful. I don't know the suggestion. I don't know much about some mechanisms, just write some usage to let everyone look. 2004-11-27 9:00

Forced transformation, whether from grammar or in words, it is one of the most difficult features in C . However, the unclearity of the semantics of C-style transformation and some potential problems are there. Mandatory type transformation is ultimately accepted by C . 1.static_castal operation symbol Static_cast (e), Stroustrup allows us to see it as an implicit conversion. This is a sense of truth. We can use the static_cast to transform the operation symbol based on implicit conversion. It is static detection, which cannot be runtably detected, especially in inheritance. Use the range <1> for transformation between all system types, can not be used for system type pointer type transformation double t_d = 0; int T_i = static_cast (t_d); // is a legal transformation to try to put Double * > int * is the transformation between <2> for inherited classes (including pointers), cannot be used for transformation inheritance between other object types without implicit conversion: Class X {}; Class Y: public X {}; use: x t_o_x; y t_o_y = static_cast (t_o_x); // x * y * Transformation can also be performed because of X, Y, the type //, the type can automatically implicitly converted using implicit conversion Example: Class X {}; Class Y {

Public: y (x i_x) {}}; x t_ox; y t_o_y = static_cast (t_o_x); // You can see Y constructor can be implicitly converted to X-type, so you can use x> y, If you attempt to report Y-> X 2. Reinterpret_cast operation is mainly used for forced transformation of type pointer type, Some_Type * -> Special_Type * This can be transformed, and the type information can be incomplete. It allows arbitrary pointers to other types of pointers, also allowing any integer type to any pointer type transformation (BT). The resulting result is extremely unsafe, unless otherwise applied, unless it is transformed into the original type. <1> Using all places can be converted to any type of pointer (the pointer is a 4-byte Long's stuff, then the machine thinks that the same type can be converted) INT C; x * p = reinterpret_cast (c) // x is a custom arbitrary type, of course, including system type <2> can transform Y * C between arbitrary type pointers; x * p = reinterpret_cast (c); // x, y represents all Custom or system types You can see that ReinterPret_cast's transformation is extremely irresponsible, and he only conveys whether it can be converted. <3> Const_cast Operation Symbol This is very simple from the name. You can see it, just to remove or add a const modifier symbol. But for the type of Const, even if you remove ConSt, you should be careful when you operate this content, you can not operate, otherwise it will be wrong. Const char * p = "123"; char * c = const_cast (p); C [0] = 1; // On the surface, the system still does not allow this when it is compiled by compiling. / / Do it. This is a vulnerability. <4> Dynamic_cast Operation Symbol Scott Mayers describes it as used to perform inheritance systems: safe down transformation or cross-transformation action. That is to say you can, use Dynamic_cast to point to the Base Class's pointer or a reference to the object of the object to the subclass. Class B {}; // Polymorphic Types Virtual Dynamic_CastClass D: Public B {} VOID F (B * PB) {D * PD1 = DYNAMIC_CAST (PB); // If the PB is returned correctly, If not returning 0d * pd2 = static_cast (PB); // None, return pointer, it is possible to point to an unsuitable pair //, because STATIC is only static, and cannot be shipped //. Whether the information is truly D Type} Terms 2: Try to use C style 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, (Type) Expression, now you should always write:

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 {...}; copiic widget {...}; void update (Specialwidget * psw); SpecialWidget SW; // SW is a non-const object const specialwidget & csw = sw; // CSW is SW A reference // is a const object Update (& CSW); // error! Cannot pass a const specialWidget * variable // give a function for processing the SpecialWidget * type variable

Update (CONST_CAST (& CSW)); / / correct, CSW Converted converts out (// CSW and SW two variable values ​​can be updated in the UPDATE / / function)

Update (SpecialWidget *) & CSW); //, but uses a more difficult to identify // type conversion

Widget * pw = new specialwidget;

Update (PW); // Error! The type of PW is widget *, but // update function is processed by specialWidget * type

Update (const_cast (pw)); // error! Const_cast can only be used in places affecting // constness or volatileness. // 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 to the UPDATE function a pointer // is a pointer to the PW of the variable type SpecialWidget to // If PW does point to an object, / / Otherwise, pass the past will make the empty pointer. Void UpdateViaref (SpecialWidget & RSW); Updateviaref (Dynamic_cast (* PW)); // is correct. Pass to the UpdateViaRef function // specialwidget PW pointer, if PW // does point to an object / / will throw an exception

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 can't use it to convert Constness:

INT firstnumber, secondnumber; ... double result = Dynamic_cast (firstnumber) / secondnumber; // error! There is no inheritance constitute const SpecialWidget Sw; ... Update (Dynamic_cast (& SW)); // Error! Dynamic_CAST cannot be converted // Remove 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 pointer pointing function //, the function is not parameter // return value type to void function type [10]; // Funcptrarray is a can hold // 10 Array of 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 look at 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) #define const_cast (type, expr) #define reinterpret_cast (type, expr) ((type) (tPR))

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 simulations do not like the real operator as safe, but when you The compiler can support new types of conversions to 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-77361.html

New Post(0)