An Unexpected Side Effect of Combining C++ Features

So, a pop quiz. Suppose you write a C++ program using class B provided in a library, like so:

#include "some-header.h"
int main() {
  B* p = new B();
  return 0;

The snippet above compiles and links just fine. So the snippet below should build too, right? Mind you, the base class is not doing anything sneaky. In particular, it does not have a private destructor, or anything else designed to interfere with derivation.

#include "some-header.h"
class D : public B {};
int main() {
  D* p = new D();
  return 0;

The answer to the quiz is that this may or may not build. It will compile, but you could get unresolved symbol errors during linking. How and when, you ask? It happens when you’re linking against a dynamically linked library (at least on Windows) and B has a protected virtual method not exported in the DLL. The explanation (as far as I can reason) hinges on the fact that the .lib for a DLL contains only the symbols marked for export. When you’re using the class directly, your compilation unit can’t access the protected virtual symbol, so the linker doesn’t look for it. But when you use the derived class you just defined, well, D can now access that protected virtual method in B, so the linker needs to find the method’s symbol. Since the symbol is not there, boom.

This situation involves no less than four distinct features coming together for the express purpose of saddening you: separate compilation, method access, inheritance, and custom symbol visibility.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s