Saturday, March 10, 2007

C++ Quiz Answers

JES raised some good points in his comment, but didn't mention the answer I had in mind. Perhaps I didn't provide enough information in the original code example. Here it is, with a couple of extra pieces of information.
class Foo {
public:
Foo(/*...*/);
~Foo();
// ...
};

unsigned char *
bar() {
// Construct a Foo into an internal character buffer based
// upon knowledge of the internal data structure of Foo,
// and return a pointer to it.
}

int main() {
// ...
Foo * foo = (Foo *)bar();
// ...
}
Despite it being strange-looking, and perhaps not supported by the Standard, the above code works (for our compiler and environment), as far as I know. It's part of a library class that I would like to make use of. Actually, I thought it would be kind of cool to use it as a base class and write several derived classes. It seemed perfect for it. Without knowing (or caring to know) the details of how it worked, I looked at the header file. I noticed that the destructor was non-virtual. Since a virtual destructor is kind of needed for base classes, I changed the destructor to be declared as virtual ~Foo(); and recompiled everything. Core dump. After taking a while to verify that I was compiling and running what I thought I was, I discovered that the use of virtual was causing the problem. I'm not an expert on this or anything, but if you have a virtual function, most C++ compilers will put the vtable pointer at the beginning of its internal representation of the class. So, the internal representation of the class is changed by making the destructor virtual, and the weird manner of construction via foo() now messes things up.

I didn't see it as my job to understand or "fix" the Foo class, so instead I created my own base class that contained a Foo and then derived classes off of that. It works, but it was frustrating to be forced into this solution for the reason I was.

C++ developers, don't code that way!

No comments: