That Thing: Function Pointers
I’m going to start a semi-repeating series on “those things.” You know how at every job, there’s always “that guy?” Or if you’re a student and your schedule is different every day, there always seems to be “that day” of the week that sucks above all others? That’s the spirit of my “that thing” rants. Today’s flavor is about pointer syntax in C++.
If you use any language long enough, you’ll learn to love it. You’ll love this core language feature, and that standard library. You’ll become accustomed to it’s minor inconveniences, and if you do it long enough, you’ll find ways to circumvent them (or at least save yourself the typing). You’ll eventually get to the point where you feel more fluent in the language than with English… or is that just me?
I digress. Anyway, if you use that language even longer, you’ll learn to hate it as well. To dread “those” moments – few and far between as they may be – when you have to perform that one annoying task that your language specification, compiler, or platform makes a chore and a half.
With C++, “that thing” (or at least one of them) is undoubtedly, above all else, the pointer. And no, I’m not talking about an unsigned*, or a bool*, or even a char* (for those who know about character arrays; real men don’t use streams). I’m not talking about any complex nested data structures with addresses scattered willy nilly all about the place.
No… what I’m talking about are function pointers. Now don’t get me wrong – function pointers, in theory, are wonderful. They prove a tremendously powerful ally on the team of anyone brave enough to employ them. And many languages pull this off without a hitch. Python makes it a breeze. It’s none too difficult in PHP, either. However, sadly enough, C++ isn’t in the cool crowd. It’s a compiled language. It needs to know what you’re doing before you do it, and it needs to know it explicitly and unambiguously. So when it comes to function pointers – especially given that they’re a higher level concept – it’s no surprise that the syntax is a bit wonky. But honestly… what is this?
class A { private: std::string (B::*_name)( void ); public: std::string (B::*getName(void))(void) { return _name; } };
Okay, declaring A::_name is a bit annoying because the compiler needs to know beyond a shadow of a doubt what the precise signature of the phantom function is. This complexity is compounded by the fact that it’s not just some regular old function, but actually a nonstatic method of class B, which takes no arguments and returns a std::string. You know what, I can dig that. I see the elegance there.
But what in the name of all that’s good and holy is going on in line 5?!?! I’m declaring a member method in A called getName, which takes no parameters, and returns the function pointer _name. Not that big of a deal. But why the convoluted syntax here? You declare any normal member method with the pattern return_type name( parameter, list ). Oh, and on line 5 there at the end, with the (void))(void)? The first void is the parameter list for A::getName and the second is the parameter list for the pointed-to member. Yeah.
I understand that function pointers require a fair bit of complexity to pull off. I also understand that what I’m doing here (returning a pointer to a nonstatic method of class B inside from a nonstatic method in class A) is fairly esoteric, however I’m flabbergasted that the syntax is so inane that I had to corroborate several Google searches to piece together the correct syntax for this. Note, in this article, I don’t even begin to consider const-ness with these puppies – yeah; that gets ugly too.
Way to be that guy, Bjarne.
I like the “that thing” series. My “that thing” happens to be Dreamweaver CS3. Unfortunately I can’t upgrade right now, either. :( I still have no idea what you’re talking about, but I enjoyed it, regardless.