why callback

You must be familiar with the callback function, which is essentially a function pointer. The operating mechanism does not need to be repeated today, only its role (necessity) will be discussed today.

I have thought about this question many years ago, but each stage may have a different experience. Today, I read a sentence about the application scenario of callback on the CSDN blog: " You want other people's code to call your function, but you can't change other people's code ".

The so-called "can't change other people's code" is actually for the purpose of encapsulation and decoupling. The other party may not really provide the source code to you. For example, the compiled module will only open an API to you. At this time, you can neither modify nor ask the other party to modify it. code. So there is only one way to pass your function to the other party through pre-defined parameters. If it's not intuitive, let's take an example:


Assuming module A (as the caller) and module B (the callee):

The work that A needs to complete is: (1) Define the callback function: void callbackfun() {...} (2) Register the callback function, that is, when calling the function func of B, pass the callback function in: func(callbackfun).

The work that B needs to complete is: define the function func, provide the API to A through the header file, and call back callbaclfun at the appropriate time in func:

                                       void func(void (*p))

                                       { ........

                                         (*p)();

                                         ........

                                       }

As can be seen from the above example, if A directly defines a function funa to implement the function of the callback function and provides it to B to call, the same function can also be achieved. It seems that there is no need to use any callback mechanism. Indeed, the implementation can be like this, but there will be two problems: (1) A calls the function of B, and B then calls the function of A, and the two modules are called cyclically. Including each other will also cause compilation problems. (2) In this way, module B hard calls the function of A, and the implementation must require that the code implementation of B needs to be modified according to the requirements of A.


So now you can appreciate the advantages of callbacks.


The following is an explanation from a CSDN netizen [TNT_snowball], which I think is really apt.


Why do we use callback functions?
I remember being asked this question by a chief interviewer during a C++ development interview, and I will answer it again now.


Our use of callback functions is nothing more than the application of function pointers. The concept of function pointers is very simple, but applying function pointers to callback functions reflects a problem-solving strategy and an idea for designing a system.
Before explaining this idea, I would like to explain that although callback functions can solve some system architecture problems, they must not be everywhere in the system. If you find that callback functions are everywhere in your system, then you must refactor your system. The callback function itself is a design idea that destroys the system structure. The callback function will absolutely change the running track, execution order, and calling order of the system. The presence of callback functions can make people reading your code very confused.


So what is a callback function? It is an unacceptable design strategy. Imagine a system implementation: in a download system, there is a file download module and a download file current progress display module. The system requires real-time display of the file. Download progress, think very simple in the object-oriented world is nothing more than to implement two classes. But the problem is precisely here, how does the display module drive the download progress bar? The display module does not know and should not know the file download progress known by the download module (the encapsulation of object-oriented design, the decoupling between modules, and the cohesion within the module), the file download progress is something only the download module can know, solve The solution is very simple to pass a function pointer to the download module as a callback function to drive the display progress of the display module.


There are quite a few such examples in the object-oriented world. The root cause of such problems, I believe everyone has realized from the above description, is the idea of ​​object-oriented programming, which is the module independence required in the design pattern. Features such as high cohesion and low coupling.


The programming strategy of encapsulating changes gives programmers the first guiding ideology is interface-oriented programming, that is, virtual-oriented programming mentioned in the design pattern rather than implementation-oriented. Such programming ideas have greatly innovated the programming world. It can be said that there is no object-oriented programming without this principle. This principle gives programming a guiding ideology, that is, how to map the reality model into the program model at a higher level. This design idea greatly promotes highly independent modules and weakens the cooperation between modules, that is, coupling, which makes modules more engaged in one-way calling work, and a module needs a certain service. Find another module, which makes the program appear hierarchical, the top layer calls the bottom layer through the interface, and the bottom layer provides services . However, in the real world, it is rare for a system that strictly follows the features of the current level. Absolute MVC does not exist, because more modules require communication and collaboration. It can be seen that without coupling, there will be no collaboration and no good calling relationship. The coupling is true. Not wrong.


Since we need cooperation between modules, and at the same time, we dislike the ambiguous relationship between you, me, and you between modules, how to generate a system? The answer is function pointers (not necessarily function pointers), that is, using callbacks Way. If an object cares about the state change of another object, then register a callback function for the state change to notify you of such state changes, so that while encapsulating the module changes, it realizes the cooperative relationship between modules. Decoupling.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325849500&siteId=291194637