|
Function References and Unions
Submitted by |
1. Function references.
Many C++ programmers know about function pointers. But far fewer know that
there are function references in C++ as well. However, because they are
references, they lack the ability to be reassigned, so their usefulness can
be questionable at times. After all, one of the most important reasons to
use function pointers is this reassignability, right?
Their syntax however, is similar to that of function pointers:
int f(int);
int (*pointer1)(int) = &f; // Address-of not strictly necessary
int (*pointer2)(int) = f;
int (&reference)(int) = f;
(*pointer1)(5); // Dereferencing not strictly necessary
pointer2(5);
reference(5); |
2. Some things you never knew about unions. (Unless you read "9.5 Unions" in
the C++ standard that is. ;)
C unions are also a widely known phenomenon. They allow multiple objects to
occupy the same memory space. In C++, unions fulfill the same role, but can
do much more. A union in C++ is in fact very much like a class. Here are
some things that a union can and can't do according to the C++ standard:
A union can have member functions (including constructors and
destructors), but not virtual functions.
A union shall not have base classes.
A union shall not be used as a base class.
An anonymous union shall not have function members.
An anonymous union shall not have private or protected members.
(Note: a union hasn't got much use for protected members anyway. It can't be
used as a base class. ;)
For those who don't know what an anonymous union is, here's a little
example:
union { int a1; float b1; }; // Anonymous union
union { int a2; float b2; } object1; // Not an anonymous union
union SomeUnion { int a3; float b3; }; // Not an anonymous union either
SomeUnion object2;
a1 = 5; // Legal
a2 = 5; // Illegal
object1.a2 = 5; // Legal
a3 = 5; // Illegal
object2.a3 = 5; // Legal |
According to the previous rules (and MSVC6 SP5) the following code is
perfectly legal:
#include <cassert
template< class T
union Vector3D
{
// Public access to x,y,z components
struct { T x, y, z; };
private:
T v3[3];
// Check for proper alignment
bool AlignmentCheck()
{
return (&v3[0] == &x) && (&v3[1] == &y) && (&v3[2] == &z);
}
public:
// Constructors
Vector3D() // Fast but potentially dangerous: no initialization
{ assert(AlignmentCheck()); }
Vector3D(T x_, T y_, T z_) : x(x_), y(y_), z(z_)
{ assert(AlignmentCheck()); }
// Accessors
T& operator[](unsigned int index)
{
assert(index < 3);
return v3[index];
}
T operator[](unsigned int index) const
{
assert(index < 3);
return v3[index];
}
// ...
}; |
I placed the alignment check in there because I'm not 100% sure if v3 and
x,y,z are guaranteed to be identically aligned for all types. In my test
code (using float, double and int) it worked like a charm though.
See also: The International C++ Standard (ISO/IEC 14882-1998). Available in
PDF for US $18 from ANSI.
|
The zip file viewer built into the Developer Toolbox made use
of the zlib library, as well as the zlibdll source additions.
|