I cannot know all the parochial terminologies and concepts used by the
great variety of the many - sometimes disputable - language designs
available in computer science. Some design choices may be motivated by
issues that are only remotely connected with science. But there is
also some more or less established terminology.
When a function A
takes a function B
as parameter, that is simply
called a functional parameter.
A function can be seen as composed of a control part (the code or
instructions) and of an environment of entities used by the control.
This environment comprises usually two kinds of program entities:
local entities that are normally intended to be used during the
lifetime of a call to the function, that have distict instances for
distinct calls, and are visible only to other entities created (declared)
in the body of the function. They come into existence at each function call, usually only for the duration of that call
global entities that are defined (declared) in some (usually) enclosing structure
(function, method, class instance ...) containing the function
declaration, hence also visible and usable by the function. They are the same for each call of the function value created by the same declaration instance.
The function code together with its associated global environment is called a
closure. The term is about 50 years old. But a closure is
essentially a functional value.
Often the conceptual closure structure can be ignored as everything
works naturally as one would hope, since a function declared in some environment usually ceases to be
accessible, thus to be used, when this environment is exited. Hence it
will no longer need what it was using there. It is however possible that a
functional value $\gamma$ leaves the environment where its has been declared, and
has to survive the disappearance of this environment where it uses some global entities. This happens mostly when another function returns $\gamma$ as a functional
result.
If function G
and variable X
are declared in function F
,
then G
can use X
as a global. It may happen that the functional
value $\gamma$ of G
is returned by a call to F
. This is no problem
because that functional value $\gamma$ can be stored in a functional
variable (some would probably say pointer) and just used from
there. The difficulty comes from the fact that when this functional
value $\gamma$ is called, it may use the variable X
of the call to
F
that created $\gamma$, and terminated returning it. So special steps must be taken to preserve
X
for the closure, even after the call to F
has terminated, and
the corresponding environment should be no longer otherwise needed.
Actually, this occurs often in object oriented programming, for
essentially the same reason. Object orientation can be implemented in
a language that does not have it precisely by declaring an object constructor
function with local variables (the state variables of the object constructed) that
return tuples of functional values (the methods of the object class) accessing these variables.
Thus the closure concept is just a very intentional and frequent
occurrence in OO programming. Every method is essentially a closure on
the environment implementing the state of an object. At each call to the constructor, a new tuple of closures is created for the new object, corresponding to function code that does not change, but which is closed on a new environment, the local environment of the constructor call that creates the object.
As said above, a closure is just a pair composed of a function and its
globals. It is not mutable: the pair is essentially fixed when the
function is created. However, the adress of such a pair is just a
pointer to a closure, and can be stored in a variable. It can be
dereferenced and called (no big mystery). But I do not know whether
that is what C++ calls a pointer to a function, though I would hope it
is.
You may note that creation of a closure has nothing to do with caller
or callee. It has to do with the function that declares the closure,
and with the function that returns it out of the environment
where its globals are defined.
I am not experienced with C# delegates (so double check me), but they
seem just to be functional types, that can have functions, closures,
or methods as instances. This typing ensures that instances are not
misused, as might happen with untyped pointers to functions. It is
not clear to me whether C# allows changing the closure associated with
a delegate instance, i.e. whether delegate instances are to be
considered functional variables or functional constants. From what I read, it seems to be the former, hence the comparison with function pointer. Why that is necessary to pass functions or methods as parameter is apparently due to specific features of C#. Other languages do not need anything special for that: they just declare the parameter like any other, but with a functional type (i.e. a signature).
I suggest you read the wikipedia articles on closure and possibly scoping
(though I have not read them in enough detail to vouch for their
accuracy).