Member function pointer and high performance C ++ entrusted (superior)

xiaoxiao2021-03-06  45

Member function pointer and high performance C entrusted (superior)

Written: Don Clugston

The primer standard C has no real object-oriented function pointer. This is unfortunate for C because it has proved its valuable value in some languages ​​because of an object-oriented pointer (also called "closure" or "delegate"). In Delphi (Object Pascal), object-oriented function pointers are the basis of the Borland visualization set library (VCL, Visual Component Library). At present, C # makes the concept of "delegate" becomes more popular, which is also showing the success of C # this language. In many applications, "delegate" simplifies the design pattern of loosely coupled objects [GOF]. This feature undoubtedly produces a lot of role in standard C . Unfortunately, there is no "delegate" in C , which only provides member function pointers. Many programmers have never used a function pointer, which is reasonable. Because the function pointer itself has a lot of strange syntax rules (such as "-> * "and". * "Operator, and it is difficult to find their accurate meaning, and you will find a better way to avoid using function pointers. More ironic is: In this article, I want to uncover the member function pointer and the "mysterious cover". After stating the grammatical and characteristics of the member function pointer, I will explain the member function pointer in some common compilers in some common compilers to achieve "delegate" to everyone. Finally, I will use these exquisite knowledge to show you a technique that implements optimization and reliable "commission" on the C compiler. For example, in Visual C (6.0, .NET, And .NET 2003), the compiler only generates two lines of assembly code! Function Pointer Let's review the function pointer. In C and C languages, a function pointer named my_func_ptr pointing to a function that is parameter with an int and a char *, which returns a floating point value, declared as follows: float (* my_func_ptr) (int, char *) In order to facilitate understanding, I highly recommend you to use the TypeDef keyword. // If this is not this, when the function pointer is passed as a function of the parameter, the program will become obscured. // This, the statement should be as follows: typedef float (* myfuncptype) (int, char *); myfuncptype my_func_ptr; note that the parameter combination of each function should be different. In Microsoft Visual C (hereinafter referred to as MSVC), there are different types of different call modes: __ cdecl, __stdcall, and __fastcall.

If your function pointer points to a function of a Float Some_Func (int, char *), you can do this: my_func_ptr = some_func; when you want to call the function it points to, you can write: (* my_func_ptr) (7, "Arbitrary String"); you can convert a type of function pointer into another function pointer type, but you can't point a function pointer to a Void * type data pointer. Other conversion operations are not detailed. A function pointer can be set to 0 to indicate that it is an empty pointer. All comparison operators (==,! =, <,>, <=,> =) Can be used, can use "== 0" or pass a explicit Boolean conversion to test the pointer is empty (NULL) . In the C language, the function pointer is usually used as a parameter like QSORT, or as a callback function of the Windows system function. There are many other applications in the function pointer. The implementation of the function pointer is simple: they are just "code pointer", which is reflected in the assembly language is the first address used to hold the subroutine code. The presence of this function pointer is just to ensure the correct invoking specification. Member Function Pointer In C programs, many functions are member functions, that is, these functions are part of a certain class. You can't point to a member function like a normal function pointer, the correct approach should be, you must use a member function pointer. The pointer of a member function points to a member function in the class, and has the same parameters as previously, the declaration is as follows: float (someclass :: * my_memfunc_ptr) (int, char *); // For member functions modified using const keyword The declaration is as follows: float (someclass :: * my_const_memfunc_ptr) (int, char *) const; note that the special operator (:: *) is used, and "SomeClass" is part of the declaration. Member function pointer has a terrible restriction: they can only point to member functions in a particular class. For each parameter, there is a need for different member function pointer types, and there are different function pointer types for each function and different classes using const modified functions and different classes. In MSVC, there is a different call type for the following four calls: __ cdecl, __stddcall, __fastcall, and __thiscall. (_Thiscall is the default way, interesting is that there is no detailed description of the __thiscall keyword in any official document, but it often appears in the error message. If you explicitly use it, you will see " It is retained an error prompt for IT IS Reserved for Future Use.) If you use a member function pointer, you'd better use TypeDef to prevent confusion.

Function pointer pointing function, such as Float SomeClass :: Some_member_func (int, char *), you can write: my_memfunc_ptr = & someclass :: Some_member_func; Many compilers (such as MSVC) will let you go to "&", and others Compiler (such as GNU G ), you need to add "&", so I suggest add it to it when you write. To call a member function pointer, you need to build an instance of SomeClass and use special operators "-> *", which is lower than the priority of this operator, you need to put it in parentheses. SomeClass * x = new SomeClass; (x -> * my_memfunc_ptr) (6, "Another Arbitrary Parameter); // If class is on the stack, you can also use the". * "Operator. SomeClass Y; (y. * My_memfunc_ptr) (15, "Different Parameters this Time"); Don't blame me for using such a strange syntax - looks that C designers have a sincere feelings for punctuation! C increases three special operators to support member pointers relative to C. ":: *" is used to declare the pointer, and "-> *" and ". *" Are used to call the functionality points to the pointer. It looks that the excessive concern of some of the part of a language blurred and fewer use is excessive. (You can of course overload "-> *" these operators, but this is not the range to be involved in this article.) A member function pointer can be set to 0, and you can use "==" and "! =" Comparison operator However, this can only be limited between the pointers of the member functions in the same class. Any member function pointer can be compared to 0 to determine if it is empty. Unlike function pointers, unequal operators (<,>, <=,> =) are not available to member function pointers. Member function pointer's weird member function pointer sometimes is very strange. First, you can't use a member function to point to a static member function, you must use a normal function pointer ("Member Function Pointer", which should actually be "non-static member function pointer" Correct). Second, when using the inheritance of the class, there will be some strange situations.

For example, the following code will compile success in MSVC (note code comment): #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 comment of the next line, the line with line (*) will appear error // Virtual void Some_member_func (int x, char * p) {printf ( "in DerivedClass");};}; int main () {// declare a member function pointer of SomeClass typedef void (SomeClass :: * SomeClassMFP) (int, char *); SomeClassMFP my_memfunc_ptr; my_memfunc_ptr = & DerivedClass :: some_member_func; // ---- line (*) returnography;} is strange, & derivedclass :: some_member_func is a member function pointer for a SomeClass class, not a member function pointer of the DeriveDclass class! (Some compilers are slightly different: For example, for Digital Mars C , in the above example, & derivedClass :: some_member_func will be considered unfained.) However, if you override (override) in the DeriveDClass class, the code is Unable to compile because the current & derivedClass :: Some_member_func has become a member function pointer in the DeriveDClass class! The type conversion between member function pointers is a very vague topic discussed. During the standardization of C , when the member function pointer involving the inherited class, for a member function pointer that converts the member function pointer to the base class or whether a member of the subclass member function pointer can be used and a class member The function pointer translates into another member function of the unrelated class, and people have had a very intense debate. Unfortunately, the different compiler producers have implemented their compilers according to their different answers to these issues before they make a decision. Based on standards (Section 5.2.2.2.2/9), you can use ReinterPret_CAST to save a member function of classes that are not related to the category of categories in a member function pointer. The final result of the issue of the member function pointer conversion is not determined. What you can do now is like previously - convert the member function pointer into a pointer to the member function of this class. Behind the article I will continue to discuss this problem, because this is a topic that each compiler has not reached a consensus on such a standard. In some compilers, there is often a strange thing between the transition between the base class and subclauses.

When involving multiple inheritance, when using ReinterPret_CAST converts subclasses into base classes, it is possible to compile a particular compiler, and may also be compiled, depending on the list of base classs in the subclass. The order of the base class! Here is an example: Class Derived: Public Base1, Public Base2 // Sample (a) Class Derived2: Public Base2, Public Base1 // Sample (b) Typedef Void (Derived :: * Derived_mfp) (); typedef void (derived2: : * Derived2_mfp) (); type1f void (base1 :: * base1mfp) (); type2 :: * base2mfp) (); derived_mfp x; for situations (a), static_cast (x) is legal And static_cast (x) is incorrect. However, the situation (b) is opposite to it. You can only transfer the members of the subclass into the member function pointer of the first base class! If you have to experiment, MSVC will issue a Warning C4407, while Digital Mars C will compile errors. If you replace Static_cast_cast, both compilers have errors, but both compilers have different reasons. But some compilers are ignored by this detail, everyone can be careful! The other interesting rules in standard C are: You can declare its member function pointer before class definition. This will have some compiler that there will be some unpredictable side effects. I will discuss this problem later, now you know how to avoid this as much as possible. It is worth noting that the Member Data Pointer is also provided like a member function pointer, standard C . They have the same operator, and some implementation principles are also the same. They are used in some implementations in Stl :: Stable_Sort, and I will no longer mention many other applications. The use of member function pointers Now you may feel that the member function pointer is a bit of strange. But what can it be used? I have made a very broad survey on this online. Finally, I summarize the two reasons for the use of member function pointers: used to do an example to see the C beginners, help them learn grammar; or to achieve "delegate"! The use of the member function pointer in the single-line function adaptor in the STL and Boost libraries is negligible and allows you to use the member function and the standard algorithm. But their most important applications are in different types of application frameworks, such as their core of the MFC message system. When you use the MFC message mapping macro (such as on_command), you will assemble a sequence containing a message ID and a member function pointer (type: ccmdtarget :: * member function pointer). This is one of the reasons why the MFC class must inherit ccmdTarget can handle the message. However, a variety of different message processing functions have different parameter lists (such as the type CDC * of the first parameter of the onDRAW processing function, so the sequence must contain various types of member function pointers.

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

New Post(0)