Function pointer with members of high-performance C + + commission (Part 1)

  Function pointer with members of high-performance C + + commission (Part 1) 

  Member Function Pointers and the Fastest Possible C + + Delegates 

  Author: Don Clugston 

  Translation: Zhou Xiang 

  Introduction 

  Standard C + + not really object-oriented function pointer.    This is the C + + is unfortunate, because the object-oriented indicators (also called "closure (closure)" or "commissioned by the (delegate)") in some languages it has proven valuable value.    In the Delphi (Object Pascal), the object-oriented function pointer is Borland visual form library (VCL, Visual Component Library) foundation.    And in the present, the C # to "trust" the increasingly popular concept, which also shows the C # language success.    In many applications, "commissioned" simplifies the design of loosely coupled object model [GoF].    No doubt these characteristics in standard C + + will be a great role. 

  Unfortunately, C + + does not "trust", it only provided a member function pointer (member function pointers).    Many programmers have never used the function pointer, which is a specific reason.    Because a lot of their own function pointer strange grammatical rules (such as "->*" and ".*" operator), but it is difficult to find the precise meaning of them, and you will find a better way to avoid the use of function pointer.    More ironic is the fact that: In fact, the compiler writers, if realized, "commissioned" then he will be hard to achieve than the member function pointer to more easily! 

  In this article, I would like to member function pointer opened the "mysterious lid."    In brief members to repeat function pointer syntax and features, I will explain to the readers some members function pointer in common is the compiler how to achieve, and then I will show you how to effectively compiler to realize "commissioned."    Finally, I would use the depth of knowledge you display in the C + + compiler to achieve optimization and reliable "commissioned" technology.    For example, in Visual C + + (6.0,. NET, and. NET 2003), commissioned by a single goal (single-target delegate) call, the compiler generated only two lines of assembly code! 

  Function pointer 

  Below we review what function pointer.    In the C and C + + languages, a function named my_func_ptr indicators point to a one and a char * int parameters for the function, the function returns a floating-point value, the statement is as follows: 

  Float (* my_func_ptr) (int, char *); 

  / / In order to facilitate understanding, I strongly recommend that you use typedef keyword. 

  / / If this does not happen, then when the function pointer parameters as a function of the transmission, 

  / / Arcane procedures will become difficult. 

  / / If this is the case, the statement should be as follows: 

  Typedef float (* MyFuncPtrType) (int, char *); 

  MyFuncPtrType my_func_ptr; 

  It should be noted that each of the parameters of a function of composition, function, the type of indicators should be different.    In the Microsoft Visual C + + (hereinafter MSVC), called on the three different methods have different types: __ cdecl, __stdcall, and __ fastcall.    If your function as indicators point to a type float some_func (int, char *) function, it can be: 

  My_func_ptr = some_func; 

  When you want to call it at the function, you can write: 

  (* My_func_ptr) (7, "Arbitrary String"); 

  You can be one type of function pointer converted into another type of a function pointer, but you should not be a function indicators point to a void * pointer data type.    Other conversion no details on the reclassification.    A function pointer can be set to 0 to indicate it is a null pointer.    All the comparison operator (==,! =, <,>, <=,> =) Can be used, you can use the "= 0" or through an explicit Boolean conversion to test whether guidelines for air (null) . 

  In the C language, the function pointer is usually used to be the same as qsort function as a parameter, or as a Windows system function callback function, and so on.    Function pointer there are many other applications.    Function pointer Implementation is very simple: they are just "code pointer (code pointer)," they reflected in the compilation of language subroutine code is used to preserve the first address.    And the existence of such a function pointer only to ensure that the correct call norms. 

  Member function pointer 

  In the C + + program, a lot of function is a member function, that is, these functions are part of a category.    You can not function as an ordinary pointer as a member at the function, the correct approach should be that you must use a member function pointer.    A member function pointer in the direction of a member function, and before and have the same parameters, the following statement: 

  Float (SomeClass:: * my_memfunc_ptr) (int, char *); 

  / / Const keyword modified for the use of members of function, the following statement: 

  Float (SomeClass:: my_const_memfunc_ptr *) (int, char *) const; 

  The use of a special operator (::*), "SomeClass" is a part of the statement.    Function pointer members have a terrible limitation: they can only point to a specific category of membership function.    For each type of parameter combinations, we need different types of function pointer, and the use of const modified for each function and the different types of functions, but also a function of different types of indicators.    In MSVC, calling on the following four methods have a different type of call: __ cdecl, __stdcall, __fastcall, and __ thiscall.    (__thiscall Default is the way it is interesting, in any official document from the right keywords __ thiscall a detailed description, but it is often in the wrong information in there. Explicit and if you use it, you will see "It was retained as an after use (it is reserved for future use)" error message.) If you use a member function pointer, you better use typedef to prevent confusion. 

  At the type of function indicators such as float SomeClass:: some_member_func (int, char *) function, you can write: 

  My_memfunc_ptr = & SomeClass:: some_member_func; 

  Many compiler (such as MSVC) will let you get rid of the "&", and some other compiler (GNU G + + for example) need to add "&" Therefore, in a handwritten procedures when I suggested that it be added.    To call members function pointer, you need to first establish a SomeClass an example, and the use of special operators "->*", this operation at the top of the lower level, you need to be properly Add in parentheses. 

  SomeClass * x = new SomeClass; 

  (X-> * my_memfunc_ptr) (6, "Another Arbitrary Parameter"); 

  / / If category in the stack, you can also use the ".*" operators. 

  SomeClass y; 

  (Y. * my_memfunc_ptr) (15, "Different parameters this time"); 

  I do not blame the use of such strange syntax - look, the designers of C + + on a punctuation heartfelt feelings!    C + C + compared to an increase of three special operators to support members of indicators.    "::*" Pointer for the statement, and "->*" and ".*" indicators pointing to a function call.    This language looks a little fuzzy and excessive use of part of the concern is redundant.    (Of course, you can override these "->*" operator, but this is not of this paper is to cover.) 

  A member function pointer can be set to 0, and can use "==" and "! =" Comparison operators, but only limited in the same category of membership function pointer between such comparisons.    Any member function pointer and 0 can be compared to determine whether it is empty.    And the function of different indicators, ranging from operators (<,>, <=,> =) member function pointer is not used. 

  Function pointer members of the weird 

  Function pointer members sometimes very strange performance.    First of all, you can not use a member function pointer point to a static member function, you must use an ordinary function pointer才行(here, "member function pointer" will be misleading, it actually should be "non-static member function pointer" that right).    Secondly, the use of the succession, there will be some rather strange situation.    For example, the following code will be compiled in the success of MSVC (Note code Note): 

  # Include "stdio.h" 

  (Class SomeClass 

  Public: 

  Virtual void some_member_func (int x, char * p) ( 

  Printf ( "In SomeClass");); 

  ); 

  Class DerivedClass: (public SomeClass 

  Public: 

  / / If you sell the Notes to the next swap with a line (*), which will be wrong 

  / / Virtual void some_member_func (int x, char * p) (printf ( "In DerivedClass");); 

  ); 

  Int main () ( 

  / / Statement SomeClass member function pointer 

  Typedef void (SomeClass:: SomeClassMFP *) (int, char *); 

  SomeClassMFP my_memfunc_ptr; 

  My_memfunc_ptr = & DerivedClass:: some_member_func; / / - line (*) 

  Return 0; 

  ) 

  It is strange that DerivedClass &:: Class SomeClass some_member_func is a member function pointer, and not a member of DerivedClass function pointer!    (Some compilers slightly different: for example, the Digital Mars C + +, in the example above, & DerivedClass:: some_member_func do not think there will be defined.) However, if the rewrite DerivedClass category (override) the some_member_func function, the code not through the compiler, because now & DerivedClass:: some_member_func DerivedClass category has become a member of function pointer! 

  Function pointer between members of the types of conversion is a discussion topic is extremely vague.    In the C + + standardization process, in relation to the succession of members of the function pointer, the function pointer members will be transformed into members of the base class function pointer into a sub-class or function pointer members of the problems and the possibility of a class members function pointer into another category is not a member of the relevant function indicators, the people there had been very heated arguments.    Unfortunately, however, the Standards Committee make a decision before the different compiler vendors have on these issues in accordance with their own different answer achieved its compiler.    According to the standard (5.2.10 / 9), you can use reinterpret_cast a member function pointer in the preservation of a type not related to the original members of the class function.    The members function pointer conversion problem, the ultimate result is not determined.    You can do now as before, or - will be members of function pointer into this category of membership function pointer.    Behind in the article, I will continue to discuss this issue because this is the various compilers of such a standard did not reach a consensus on the topic. 

  In some compiler, in the base class and subclass indicator function of the members of conversion between the often strange things happen.    When it comes to multiple inheritance, the use of reinterpret_cast will be converted into sub-categories-category, for a particular compiler compiler is likely to pass, and may also be passed compiler, depending on the category of the base class list The order of the base class!    Below is an example: 

  Class Derived: public Base1, public Base2 / / (a) 

  Class Derived2: public Base2, public Base1 / / (b) 

  Typedef void (Derived:: * Derived_mfp) (); 

  Typedef void (Derived2:: * Derived2_mfp) (); 

  Typedef void (Base1:: * Base1mfp) (); 

  Typedef void (Base2:: * Base2mfp) (); 

  Derived_mfp x; 

  For (a), static_cast <Base1mfp>    (X) is legitimate, and static_cast <Base2mfp>    (X) is wrong.    But (b) is the contrary.    You can only type of security will be a member of function pointer into a base class member function pointer!    If you want to experiment, MSVC C4407, will be issued a warning, and Digital Mars C + + will compile errors.    If reinterpret_cast static_cast instead, the two will compiler error, but the two compilers have different reasons for this.    However, some details of this compiler ignored, what will happen to you! 

  Standard C + + Another one of the interesting rules is: you can type in the definition of the statement before its members function pointer.    Compiler for some there will be some unpredictable side effects.    I will be discussing this issue, as long as you are aware of the need to avoid as far as possible in this situation yourself. 

  It is noteworthy that need, as members of function pointer, standard C + + provides a member of the same data pointer (member data pointer).    They have the same operator, but there are some principles to achieve is the same.    Use them in the stl:: stable_sort achieve some programmes, and many other applications this, I will no longer mentioned. 

  The use of function pointer 

  Now you may think that some members of function pointer is singular.    But it can be used to do what?    I do online in a very extensive investigation.    Finally, I summed up the use of the function pointer two reasons: 

  •   Used as examples for C + + beginners, helping them learn grammar or 

  •   In order to achieve "commissioned by the (delegate)." 

  Member function pointer in the STL and Boost function of a single adapter (one-line function adaptor) is the use of small, but allows you to the members of function and standard algorithm mixed use.    But their most important applications in the different types of applications in the framework, for example, they formed the core of MFC Message System. 

  When you use the MFC-mapping information (for example ON_COMMAND), you will include an assembly member ID and information function pointer (such as type: CCmdTarget:: * Membership function pointer) sequences.    This is the MFC category must inherit CCmdTarget news can be dealt with only one of the reasons why.    However, a variety of different information processing function of the list of parameters (such as OnDraw function of a deal with the types of parameters for CDC *), the sequence must include members of all the different types of function pointer.    MFC is how do this?    MFC use of a terrible loophole in the compiler (hack), it will all possible members of function pointer into a huge joint (union), thereby avoiding the need for the usual C + + types of matches.    (A look at afximpl.h and cmdtarg.cpp MessageMapFunctions called in the union, you will find this horrible fact.) Because MFC is such an important part of the code, so the fact is that all the compiler for all this loophole open the green light.    (However, at the back we will see if some type uses multiple inheritance, this loophole in MSVC on will not work, this is the use of MFC must be used only when a single inheritance reasons.) 

  In the boost:: function in a similar gap (but not too serious).    If you want to look any function pointer of the members of the more interesting things you must do a good job with the loopholes in the language challenge preparations.    If you want to negate the C + + member function pointer of the defective design perspective, it seems that it is very difficult. 

  In writing this article, there is one point I need to specify: "allows members to convert between the function pointer (cast), and does not allow a change in one call after the completion of the function", the rules included in the C + + standard is ridiculous.    First of all, many popular compilers do not support this conversion (Therefore, the conversion is standard requirements, but it is not portable).    Secondly, the compiler of all, if successful conversion, after calling members of conversion function pointer can still achieve your desired function: the compiler will be no so-called "undefined behavior (undefined behavior)," the need for such errors of the (call (Invocation) is feasible, but instead of the standard!).    Third, it allows conversion and the call is not entirely useless, only conversion and calls are feasible, and to facilitate the effective realization of commission, so that the language benefit. 

  In order to let you are convinced that this controversial thesis, consider a document only in the following section of code, the code is legitimate: 

  Class SomeClass; 

  Typedef void (SomeClass:: SomeClassFunction *) (void); 

  Void Invoke (SomeClass * pClass, SomeClassFunction funcptr) ( 

  (PClass-> * funcptr) ();); 

  Note that the compiler must generate code compilation function pointer to call members, in fact compiler of the SomeClass ignorant.    Clearly, unless the links with a number of extreme refinement of optimization measures, otherwise the code will be ignored and the actual definition of the right to run.    And as a direct result of this is that you can "safe" call from a totally different type of conversion from other members of function pointer. 

  I explained to the assertion that the other half - and not in accordance with the standards conversion by the way, I need to discuss the details of how to achieve compiler is the member function pointer.    I will also explain why the use of the rules of function pointer is so severely restricted.    Obtain detailed discussion of the document function pointer is not too easy, and we have been on the wrong words used, so, I carefully examined a series of compiler code generation compilation…… 

  (To be continued) 

Bookmark it: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • Sphinn
  • del.icio.us
  • Google
  • DotNetKicks
  • DZone
  • Furl
  • Netvouz

Tags:

Releated Articles


0 Comments to “Function pointer with members of high-performance C + + commission (Part 1)”

No Comments. Send your comment.

Leave a Reply

You must be logged in to post a comment.