Function Pointer

  • July 2020
  • PDF

This document was uploaded by user and they confirmed that they have the permission to share it. If you are author or own the copyright of this book, please report to us by using this DMCA report form. Report DMCA


Overview

Download & View Function Pointer as PDF for free.

More details

  • Words: 4,273
  • Pages: 9
Function Pointer Posted in C/C++ by Hoang Tran on the November 26th, 2007 Bài viết về function pointer được trích dịch từ tài liệu này: http://www.newty.de/fpt/index.html

1. 1 Giới thiệu 1. 1.1 Function Pointer là gì? 2. 1.2 Thay thế câu lệnh Switch như thế nào? 2. 2 Syntax của C và C++ function pointer 1. 2.1 Define một function pointer 2. 2.2 Calling Convention 3. 2.3 Gán một địa chỉ vào function pointer 4. 2.4 So sánh các function pointer 5. 2.5 Gọi một hàm sử dụng function pointer 6. 2.6 Truyền function pointer như là một tham số 7. 2.7 Trả về một function pointer 8. 2.8 Sử dụng một mảng các function pointer 3. 3 Implement Callback Functions in C and C++ 1. 3.1 Khái niệm về callback function 2. 3.2 Implement a callback function in C 3. 3.3 Implement a Callback to a static C++ Member Function 4. 3.4 Implement a Callback to a non-static C++ Member Function

1 Giới thiệu Function Pointer cung cấp một kỹ thuật lập trình cực kỳ thú vị, hiệu quả và “đầy màu sắc”. Chúng ta có thể sử dụng nó để thay thế câu lệnh switch/if, xây dựng quá trình late-binding hoặc implement hàm callback. Tiếc thay, có thể vì sự phức tạp của nó mà nó được đề cập rất ít trong hầu hết sách và tài liệu. Nếu có thì nó chỉ được trình bày một cách rất tóm tắt và sơ sài. Thực ra thì nó ít gây ra lỗi hơn so với pointer bình thường bởi vì chúng ta không bao giờ phải allocate hoặc de-allocate bộ nhớ cả. Tất cả việc chúng ta cần làm là hiểu nó làm gì và học cú pháp của nó. Nhưng hãy luôn tâm niệm rằng: hãy tự hỏi bạn có thực sự cần đến function pointer hay không? Rất tuyệt để thể hiện cách thức late-binding, thế nhưng sử dụng cấu trúc hiện tại của C++ làm cho đoạn mã trở nên dễ đọc và rõ ràng hơn. Một khía cạnh khác của late-binding là runtime: nếu bạn gọi một virtual function, chương trình sẽ xác định hàm nào được gọi. Nó làm điều đó bằng cách sử dụng V-Table mà chứa tất cả những hàm có thể gọi. Điều đó có vẻ hơi lãng phí mỗi lần gọi, và có thể bạn sẽ tiết kiệm một chút nếu sử dụng function pointer thay vì virtual function. Cũng có thể không …

1.1 Function Pointer là gì? Function pointer là một pointer mà nó chỉ đến địa chỉ của một hàm. Bạn phải luôn giữ trong đầu rằng một chương trình chạy sẽ chiếm một không gian bộ nhớ xác định trong bộ nhớ chính. Cả đoạn chương trình thực thi đã được dịch từ mã mà bạn viết và các biến sử dụng đều được đưa vào trong không gian bộ nhớ này. Vì vậy một function trong chương trình của bạn không có gì khác hơn là một địa chỉ trong bộ nhớ.

1.2 Thay thế câu lệnh Switch như thế nào? Khi chúng ta muốn gọi một hàm DoIt() ở một label xác định trong chương trình, chúng ta phải để lời gọi tới hàm DoIt() tại label đó. Sau đó biên dịch và mỗi khi chương trình chạy tới label đó thì hàm DoIt() sẽ được gọi. Mọi thứ đều ok, nhưng sẽ làm gì nếu giả sử chúng ta không biết tại thời điểm build-time (thời gian dịch) hàm nào sẽ được gọi? Nghĩa là chỉ đến lúc chạy ta mới biết ở label đó thì nên chạy DoIt() hay một hàm nào khác. Đó chính là lúc chúng ta muốn sử dụng đến callback-function hoặc là sử dụng kỹ thuật lấy ra từ một “pool” chứa các possible function. Tuy nhiên thì chúng ta có thể giải quyết vấn đề này bằng cách sử dụng lệnh switch, và lựa chọn lời gọi đến hàm thích hợp ở những

nhánh khác nhau tùy theo giá trị biểu thức của switch. Nhưng vẫn có một cách khác là sử dụng function pointer. Trong ví dụ sau đây chúng ta thực hiện nhiệm vụ của bốn toán tử toán học cơ bản (+, -, *, /). Cách đầu tiên sử dụng switch và cách thứ hai sử dụng function pointer. //-----------------------------------------------------------------------------// 1.2 Introductory Example or How to Replace a Switch-Statement // Task: Perform one of the four basic arithmetic operations specified by the // characters '+', '-', '*' or '/'. // The four arithmetic operations ... one of these functions is selected // at runtime with a swicth or a function pointer float Plus (float a, float b) { return a+b; } float Minus (float a, float b) { return a-b; } float Multiply(float a, float b) { return a*b; } float Divide (float a, float b) { return a/b; } // Solution with a switch-statement - specifies which operation to execute void Switch(float a, float b, char opCode) { float result; // execute operation switch(opCode) { case '+' : result = Plus (a, b); break; case '-' : result = Minus (a, b); break; case '*' : result = Multiply (a, b); break; case '/' : result = Divide (a, b); break; } cout << "Switch: 2+5=" << result << endl; // display result } // Solution with a function pointer - is a function pointer and points to // a function which takes two floats and returns a float. The function pointer // "specifies" which operation shall be executed. void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float)) { float result = pt2Func(a, b); // call using function pointer cout << "Switch replaced by function pointer: 2-5="; // display result cout << result << endl; } // Execute example code void Replace_A_Switch() { cout << endl << "Executing function 'Replace_A_Switch'" << endl; Switch(2, 5, /* '+' specifies function 'Plus' to be executed */ '+'); Switch_With_Function_Pointer(2, 5, /* pointer to function 'Minus' */ &Minus); } Chú ý: Một function pointer luôn trỏ đến một function đặc biệt nên tất cả những function mà chúng ta muốn sử dụng với cùng một function pointer thì phải có cùng tham số và giá trị trả về. Nói một cách khác là cùng prototype.

2 Syntax của C và C++ function pointer Dựa vào cú pháp thì có hai loại function pointer khác nhau: một là những function pointer trỏ đến C function hoặc static C++ member function, một là những function pointer tới non-static C++ member function. Sự khác biệt cơ bản là tất cả pointer đến non-static member function cần một tham số ẩn: con trỏ this tới instance của class. Vậy chỉ cần nhớ rằng có hai loại function pointer không tương thích với nhau.

2.1 Define một function pointer Vì function pointer không khác gì hơn một biến nên nó phải được define giống như thông thương. Ví dụ dưới đây chúng ta khai báo các function pointer tên là pt2Function, pt2Member và pt2ConstMember. Chúng trở đến function và lấy một biến float và hai biến char và trả về một số int. Ở ví dụ C++ chúng ta giả sử rằng function mà function pointer trỏ đến là non-static member function của TMyClass. // 2.1 define a function pointer and initialize to NULL int (*pt2Function)(float, char, char) = NULL; // C int (TMyClass::*pt2Member)(float, char, char) = NULL; // C++ int (TMyClass::*pt2ConstMember)(float, char, char) const = NULL; // C++

2.2 Calling Convention Thông thường chúng ta không phải nghĩ về calling convention của một function. Trình biên dịch giả định rằng cdecl là convention mặc định nếu chúng ta không sử dụng một convention khác. Nếu bạn muốn tìm hiểu kỹ hơn hãy tìm đọc. Calling convention nói cho trình biên dịch biết cách truyền tham số và cách tạo ra một function. Ví dụ về những calling convention khác là stdcall, pascal, fastcall. Nếu function và function pointer khác calling convention thì chúng cũng không tương thích với nhau và không thể thực hiện phép gán function pointer vào địa chỉ của function kia. Đối với trình biên dịch của Borland và Microsoft thì cần khai báo calling convention ở giữa kiểu trả về và tên hàm hay tên function pointer. Đối với GNU GCC thì sử dụng từ khóa __attribute__: viết khai báo hàm theo sau bởi từ khóa __attribute__ và sau đó là trạng thái của calling convention ở trong1. // 2.2 define the calling convention void __cdecl DoIt(float a, char b, char c); // Borland and Microsoft void DoIt(float a, char b, char c) __attribute__((cdecl)); // GNU GCC 2.3 Gán một địa chỉ vào function pointer Rất dễ dàng để gán một địa chỉ của một function vào function pointer. Đơn giản chỉ cần lấy tên của function hoặc member function thích hợp. Mặc dù hầu hết các compiler support việc đó nhưng tốt hơn hết là chúng ta sử dụng toán tử địa chỉ & và đặt trước các function name để viết những đoạn mã portable. Chúng ta cũng phải sử dụng tên đầy đủ của member function bao gồm tên lớp và toán tử scope (::). Chúng ta cũng phải đảm bảo rằng chúng ta được quyền truy nhập vào function ở bên trong scope đó. // 2.3 assign an address to the function pointer // Note: Although you may ommit the address operator on most compilers // you should always use the correct way in order to write portable code. // C int DoIt (float a, char b, char c) { printf("DoIt\n"); return a+b+c; } int DoMore(float a, char b, char c)const { printf("DoMore\n"); return a-b+c; } pt2Function = DoIt; // short form pt2Function = &DoMore; // correct assignment using address operator // C++ class TMyClass { public: int DoIt(float a, char b, char c) { cout << "TMyClass::DoIt"<< endl; return a+b+c; }; int DoMore(float a, char b, char c) const { cout << "TMyClass::DoMore" << endl; return a-b+c; }; /* more of TMyClass */ }; pt2ConstMember = &TMyClass::DoMore; // correct assignment using address operator

pt2Member = &TMyClass::DoIt; // note: may also legally point to &DoMore 2.4 So sánh các function pointer Chúng ta có thể sử dụng các toán tử so sánh (==, !=) như bình thường. Trong ví dụ dưới đây nó được kiểm tra xem pt2Function và pt2Member có thực sự chứa địa chỉ của hàm DoIt() và TMyClass::DoMore() // 2.4 comparing function pointers // C if(pt2Function >0) { // check if initialized if(pt2Function == &DoIt) printf("Pointer points to DoIt\n"); } else printf("Pointer not initialized!!\n"); // C++ if(pt2ConstMember == &TMyClass::DoMore) cout << "Pointer points to TMyClass::DoMore" << endl; 2.5 Gọi một hàm sử dụng function pointer Trong C, chúng ta gọi một hàm sử dụng function pointer bằng cách explicitly dereferencing nó bằng toán tử *. Một lựa chọn khác là sử dụng function pointer thay vì function name. Trong C++ hai toán tử .* và ->* được sử dụng cùng với instance của một class để gọi một (non-static) member function. Nếu lời gọi diễn ra bên trong một member function khác, chúng ta có thể sử dụng con trỏ this. // 2.5 calling a function using a function pointer int result1 = pt2Function (12, 'a', 'b'); // C short way int result2 = (*pt2Function) (12, 'a', 'b'); // C TMyClass instance1; int result3 = (instance1.*pt2Member)(12, 'a', 'b'); // C++ int result4 = (*this.*pt2Member)(12, 'a', 'b'); // C++ if this-pointer can be used TMyClass* instance2 = new TMyClass; int result4 = (instance2->*pt2Member)(12, 'a', 'b'); // C++, instance2 is a pointer delete instance2;

2.6 Truyền function pointer như là một tham số Chúng ta có thể truyền function pointer như một tham số của một function được gọi khác. Điều đó rất cần thiết nếu chúng ta muốn truyền một con trỏ tới một callback function. Đoạn mã dưới đây chỉ cách truyền một pointer tới một function mà trả về một số nguyên và lấy một số float và 2 char làm tham số: //-----------------------------------------------------------------------------------// 2.6 How to Pass a Function Pointer // is a pointer to a function which returns an int and takes a float and two char void PassPtr(int (*pt2Func)(float, char, char)) { int result = (*pt2Func)(12, 'a', 'b'); // call using function pointer cout << result << endl; } // execute example code - 'DoIt' is a suitable function like defined above in 2.1-4 void Pass_A_Function_Pointer() { cout << endl << "Executing 'Pass_A_Function_Pointer'" << endl; PassPtr(&DoIt); } 2.7 Trả về một function pointer Hơi mẹo một chút nhưng một function pointer có thể là giá trị trả về của một function. Trong ví dụ sau đây có hai giải pháp cho việc trả về một function pointer. Nếu muốn trả về một pointer vào một member function, chúng ta phải thay đổi definitions và declarations của tất cả các function pointer. //-----------------------------------------------------------------------------------// 2.7 How to Return a Function Pointer

// 'Plus' and 'Minus' are defined above. They return a float and take two float // Direct solution: Function takes a char and returns a pointer to a // function which is taking two floats and returns a float. // specifies which function to return float (*GetPtr1(const char opCode))(float, float) { if(opCode == '+') return &Plus; else return &Minus; } // default if invalid operator was passed // Solution using a typedef: Define a pointer to a function which is taking // two floats and returns a float typedef float(*pt2Func)(float, float); // Function takes a char and returns a function pointer which is defined // with the typedef above. specifies which function to return pt2Func GetPtr2(const char opCode) { if(opCode == '+') return &Plus; else return &Minus; // default if invalid operator was passed } // Execute example code void Return_A_Function_Pointer() { cout << endl << "Executing 'Return_A_Function_Pointer'" << endl; // define a function pointer and initialize it to NULL float (*pt2Function)(float, float) = NULL; pt2Function=GetPtr1('+'); // get function pointer from function 'GetPtr1' cout << (*pt2Function)(2, 4) << endl; // call function using the pointer pt2Function=GetPtr2('-'); // get function pointer from function 'GetPtr2' cout << (*pt2Function)(2, 4) << endl; // call function using the pointer } 2.8 Sử dụng một mảng các function pointer Sử dụng một mảng các function pointer khá thú vị. Nó cho phép khả năng lựa chọn một function sử dụng chỉ số (index). Cú pháp thì khá phức tạp và thường xuyên dẫn đến sự nhầm lẫn. Đoạn mã dưới đây bạn sẽ tìm thấy hai cách sử dụng một mảng các function pointer trong C và C++. Cách thứ nhất sử dụng typedef và cách thứ hai sử dụng trức tiếp cách khai bao mảng. Nó tùy thuộc vào bạn thích cách nào hơn. //-----------------------------------------------------------------------------------// 2.8 How to Use Arrays of Function Pointers // C --------------------------------------------------------------------------------// type-definition: 'pt2Function' now can be used as type typedef int (*pt2Function)(float, char, char); // illustrate how to work with an array of function pointers void Array_Of_Function_Pointers() { printf("\nExecuting 'Array_Of_Function_Pointers'\n"); // define arrays and ini each element to NULL, and are arrays // with 10 pointers to functions which return an int and take a float and two char // first way using the typedef pt2Function funcArr1[10] = { NULL }; // 2nd way directly defining the array int (*funcArr2[10])(float, char, char) = { NULL }; // assign the function's address - 'DoIt' and 'DoMore' are suitable functions // like defined above in 2.1-4 funcArr1[0] = funcArr2[1] = &DoIt; funcArr1[1] = funcArr2[0] = &DoMore; /* more assignments */ // calling a function using an index to address the function pointer printf("%d\n", funcArr1[1](12, 'a', 'b')); // short form printf("%d\n", (*funcArr1[0])(12, 'a', 'b')); // "correct" way of calling printf("%d\n", (*funcArr2[1])(56, 'a', 'b')); printf("%d\n", (*funcArr2[0])(34, 'a', 'b')); } // C++-------------------------------------------------------------------------------

// type-definition: 'pt2Member' now can be used as type typedef int (TMyClass::*pt2Member)(float, char, char); // illustrate how to work with an array of member function pointers void Array_Of_Member_Function_Pointers() { cout << endl << "Executing 'Array_Of_Member_Function_Pointers'" << endl; // define arrays and ini each element to NULL, and are // arrays with 10 pointers to member functions which return an int and take // a float and two char // first way using the typedef pt2Member funcArr1[10] = { NULL }; // 2nd way of directly defining the array int (TMyClass::*funcArr2[10])(float, char, char) = { NULL }; // assign the function's address - 'DoIt' and 'DoMore' are suitable member // functions of class TMyClass like defined above in 2.1-4 funcArr1[0] = funcArr2[1] = &TMyClass::DoIt; funcArr1[1] = funcArr2[0] = &TMyClass::DoMore; /* more assignments */ // calling a function using an index to address the member function pointer // note: an instance of TMyClass is needed to call the member functions TMyClass instance; cout << (instance.*funcArr1[1])(12, 'a', 'b') << endl; cout << (instance.*funcArr1[0])(12, 'a', 'b') << endl; cout << (instance.*funcArr2[1])(34, 'a', 'b') << endl; cout << (instance.*funcArr2[0])(89, 'a', 'b') << endl; }

3 Implement Callback Functions in C and C++

3.1 Khái niệm về callback function Function pointer cung cấp khái niệm về callback function. Trong bài viết này sẽ giới thiệu về callback function thông qua một hàm về giải thuật sắp xếp nổi tiếng là qsort. Hàm này sẽ sắp xếp các phần tử theo một tiêu chuẩn sắp xếp mà user định nghĩa. Kích thước của một item và số item cần sắp xếp sẽ được truyền vào hàm này. Câu hỏi đặt ra là: làm thế nào để hàm qsort có thể sắp xếp các phần tử mà không có một thông tin gì về kiểu của phần tử sắp xếp? Câu trả lời rất đơn giản: hàm qsort sẽ nhận một function pointer tới một hàm so sánh như một tham số. Hàm so sánh sẽ nhận hai tham số kiểu con trỏ void tới hai phần tử và sẽ đánh giá thứ tự của hai phần tử đó và trả về một số int. Do đó mỗi lần giải thuật sắp xếp cần đánh giá ví trí của hai phần tử thì đơn giản chỉ là gọi tới hàm so sánh thông qua function pointer.

3.2 Implement a callback function in C Hãy tham khảo khai báo của hàm qsort dưới đây: void qsort(void* field, size_t nElements, size_t sizeOfAnElement, int(_USERENTRY *cmpFunc)(const void *, const void*)); field trỏ tới phần tử đầu tiên của mảng cần sắp xếp, nElements là số phần tử cần sắp xếp, sizeOfAnElement là kích thước của một phần tử tính theo byte, và cmpFunc là function pointer tới hàm so sánh. Hàm so sánh này lấy hai phần tử const void* và trả về một số nguyên. void qsort( ... , int(_USERENTRY *cmpFunc)(const void*, const void*)) { /* sort algorithm - note: item1 and item2 are void-pointers */ int bigger=cmpFunc(item1, item2); // make callback /* use the result */ } Ví dụ mẫu sử dụng qsort

//----------------------------------------------------------------------------------------// 3.3 How to make a callback in C by the means of the sort function qsort #include <stdlib.h> // due to: qsort #include // randomize #include <stdio.h> // printf // comparison-function for the sort-algorithm // two items are taken by void-pointer, converted and compared int CmpFunc(const void* _a, const void* _b) { // you've got to explicitly cast to the correct type const float* a = (const float*) _a; const float* b = (const float*) _b; if(*a > *b) return 1; // first item is bigger than the second one -> return 1 else if(*a == *b) return 0; // equality -> return 0 else return -1; // second item is bigger than the first one -> return -1 } // example for the use of qsort() void QSortExample() { float field[100]; ::randomize(); // initialize random-number-generator for(int c=0;c<100;c++) // randomize all elements of the field field[c]=random(99); // sort using qsort() qsort((void*) field, /*number of items*/ 100, /*size of an item*/ sizeof(field[0]), /*comparison-function*/ CmpFunc); // display first ten elements of the sorted field printf("The first ten elements of the sorted field are ...\n"); for(int c=0;c<10;c++) printf("element #%d contains %.0f\n", c+1, field[c]); printf("\n"); }

3.3 Implement a Callback to a static C++ Member Function Implement callback tới static C++ member function cũng giống như implement callback tới hàm C. Static member function không cần một object để thực thi vì vậy nó phải có cùng một prototype như là hàm C với cùng một calling convention, tham số và giá trị trả về.

3.4 Implement a Callback to a non-static C++ Member Function Function pointer tới non-static member thì khác với là một con trỏ hàm C vì nó cần phải truyền một con trỏ this của object. Nếu bạn chỉ muốn gọi hàm callback tới một member function của một class cụ thể thì chỉ cần chuyển đoạn mã từ một function pointer bình thường tới con trỏ tới member function. Nhưng sẽ làm thế nào nếu muốn gọi hàm callback tới một non-static member của một class chưa rõ nào đó (có thể ở các class khác nhau). Nó khó hơn một chút. Chúng ta cần phải viết một static member function như là một wrapper. Static member function thì được coi như là một function bình thường. Sau đó thì chúng ta sẽ ép kiểu con trỏ tới object mà chúng ta muốn nó thực hiện member function, thành void* và truyền nó tới wrapper như là một tham số phụ thêm hoặc là thông qua một biến toàn cục. Tất nhiên chúng ta cũng truyền các tham số gọi tới member function. Wrapper sẽ ép kiểu con trỏ void thành con trỏ tới object của class tương ứng của nó và gọi member function (kỹ thuật này giống với kỹ thuật chúng ta xây dựng class Thread). Dưới đây là hai ví dụ: Ví dụ A: Con trỏ tới object được truyền như là một tham số phụ thêm: Hàm DoItA() thực hiện với object của class TClassA để gọi hàm callback. Vì vậy con trỏ tới object của class TClassA và con trỏ tới static wrapper function TClassA::Wrapper_To_Call_Display được truyền tới DoItA(). Hàm wrapper này là callback function. Chúng ta có thể viết những class khác giống như TClassA và sử dụng chung với DoItA miễn là những class này cũng cung cấp các function cần thiết. Chú ý là giải pháp này có thể hữu dụng nếu chúng ta tự thiết kế giao diện của hàm callback. Nó tốt hơn rất nhiều so với giải pháp thứ hai sử dụng biến toàn cục. //----------------------------------------------------------------------------------------// 3.5 Example A: Callback to member function using an additional argument // Task: The function 'DoItA' makes something which implies a callback to

// the member function 'Display'. Therefore the wrapper function // 'Wrapper_To_Call_Display is used. #include // due to: cout class TClassA { public: void Display(const char* text) { cout << text << endl; }; static void Wrapper_To_Call_Display(void* pt2Object, char* text); /* more of TClassA */ }; // static wrapper function to be able to callback the member function Display() void TClassA::Wrapper_To_Call_Display(void* pt2Object, char* string) { // explicitly cast to a pointer to TClassA TClassA* mySelf = (TClassA*) pt2Object; // call member mySelf->Display(string); } // function does something which implies a callback // note: of course this function can also be a member function void DoItA(void* pt2Object, void (*pt2Function)(void* pt2Object, char* text)) { /* do something */ pt2Function(pt2Object, "hi, i'm calling back using a argument ;-)"); // make callback } // execute example code void Callback_Using_Argument() { // 1. instantiate object of TClassA TClassA objA; // 2. call 'DoItA' for DoItA((void*) &objA, TClassA::Wrapper_To_Call_Display); } Ví dụ B: Con trỏ tới object được lưu trữ trong một biến toàn cục. Hàm DoItB sẽ thực hiện với đối tượng của class B để gọi hàm callback. Một con trỏ tới static wrapper function TClassB::Wrapper_To_Call_Display được truyền vào DoItB. Hàm wrapper này là callback function. Wrapper sử dụng biến toàn cục void* pt2Object và phép ép kiểu thành một đối tượng của TClassB. Phải luôn chú ý khởi tạo biến toàn cục để chỉ đến đối tượng của class chính xác. Chúng ta có thể viết những class khác như TClassB và sử dụng chúng với DoItB miễn là những class đó cung cấp các function cần thiết. Cách này không phải là một giải pháp tốt bởi vì sử dụng biến toàn cục rất nguy hiểm và có thể gây ra những lỗi nghiêm trọng. //-----------------------------------------------------------------------------// 3.5 Example B: Callback to member function using a global variable // Task: The function 'DoItB' makes something which implies a callback to // the member function 'Display'. Therefore the wrapper function // 'Wrapper_To_Call_Display is used. #include // due to: cout void* pt2Object; // global variable which points to an arbitrary object class TClassB { public: void Display(const char* text) { cout << text << endl; }; static void Wrapper_To_Call_Display(char* text); /* more of TClassB */ }; // static wrapper function to be able to callback the member function Display() void TClassB::Wrapper_To_Call_Display(char* string) { // explicitly cast global variable to a pointer to TClassB // warning: MUST point to an appropriate object! TClassB* mySelf = (TClassB*) pt2Object; // call member mySelf->Display(string); } // function does something which implies a callback // note: of course this function can also be a member function void DoItB(void (*pt2Function)(char* text)) { /* do something */ pt2Function("hi, i'm calling back using a global ;-)"); // make callback } // execute example code

void Callback_Using_Global() { // 1. instantiate object of TClassB TClassB objB; // 2. assign global variable which is used in the static wrapper function // important: never forget to do this!! pt2Object = (void*) &objB; // 3. call 'DoItB' for DoItB(TClassB::Wrapper_To_Call_Display); }

Related Documents