[Home]
[Search]
[D]
Functions
Virtual Functions
All non-static member functions are virtual. This may sound
inefficient, but since the D compiler knows all of the class
heirarchy when generating code, all
functions that are not overridden can be optimized to be non-virtual.
In fact, since
C++ programmers tend to "when in doubt, make it virtual", the D way of
"make it
virtual unless we can prove it can be made non-virtual" results on
average much
more direct function calls. It also results in fewer bugs caused by
not declaring
a function virtual that gets overridden.
Functions with non-D linkage cannot be virtual, and hence cannot be overridden.
Inline Functions
There is no inline keyword. The compiler makes the decision whether to
inline a function or not, analogously to the register keyword no
longer being relevant to a
compiler's decisions on enregistering variables.
(There is no register keyword either.)
Function Overloading
In C++, there are many complex levels of function overloading, with
some defined as "better" matches than others. If the code designer
takes advantage of the more subtle
behaviors of overload function selection, the code can become
difficult to maintain. Not
only will it take a C++ expert to understand why one function is
selected over another, but different C++ compilers can implement
this tricky feature differently, producing
subtly disastrous results.
In D, function overloading is simple. It matches exactly, it matches with
implicit conversions, or it does not match. If there is more than one match, it is an error.
Functions defined with non-D linkage cannot be overloaded.
Function Parameters
Parameters are in, out, or inout.
in is the default; out and inout work like
storage classes. For example:
int foo(int x, out int y, inout int z, int q);
x is in, y is out, z is inout, and q is in.
out is rare enough, and inout even rarer, to
attach the keywords to
them and leave in as
the default. The reasons to have them are:
- The function declaration makes it clear what the inputs and
outputs to the function
are.
- It eliminates the need for IDL as a separate language.
- It provides more information to the compiler, enabling more
error checking and
possibly better code generation.
- It (perhaps?) eliminates the need for reference (&) declarations.
out parameters are set to the default initializer for the
type of it. For example:
void foo(out int bar)
{
}
int bar = 3;
foo(bar);
// bar is now 0
Local Variables
It is an error to use a local variable without first assigning it a
value. The implementation may not always be able to detect these
cases. Other language compilers sometimes issue a warning for this,
but since it is always a bug, it should be an error.
It is an error to declare a local variable that is never referred to.
Dead variables, like anachronistic dead code, is just a source of
confusion for maintenance programmers.
It is an error to declare a local variable that hides another local
variable in the same function:
void func(int x)
{ int x; error, hides previous definition of x
double y;
...
{ char y; error, hides previous definition of y
int z;
}
{ wchar z; legal, previous z is out of scope
}
}
While this might look unreasonable, in practice whenever
this is done it either is a
bug or at least looks like a bug.
It is an error to return the address of or a reference to a
local variable.
It is an error to have a local variable and a label with the same name.
Copyright (c) 1999-2001 by Digital Mars, All Rights Reserved