Letter the Fifth – Evils of Inheritance

29Dec09

My Dear Malware,

As the Old Year crawls to its sorry end, I find it useful to look back on the achievements of the past few months. One technique that I have had much success with is suggesting to our pathetic human patients (has the word “developer” ever been so misapplied?) that they extend the C++ Standard Library containers using inheritance.


You probably have come across the situation many times. The “developer” notices that a class such as std::string is missing a useful function. For example, it has no function to “peek” at a possibly invalid location:

std::string s = "abc";
char c1 = s[1];        // returns 'b'
char c2 = s[100];    // undefined behaviour
char c3 = s.Peek( 100 );   // returns '0'

The developer thinks that it might be nice to have such a function to extend the string class. And here is where you must strike immediately! Your first action should be to whisper in his ear that he modifies the code for his implementation of the standard library. As std::string is often implemented at least partly via header files, this is certainly possible.

Unfortunately, not even the most misguided C++ developer will feel too happy messing around with the often obfuscated code in the library implementation. They may even know that introducing functions like Peek() into the std:: namespace is forbidden by the C++ Standard. This is where you must use your second option – suggest to them that they derive a new string class from std::string:

class MyString : public std::string {
    public:
        char Peek( unsigned int i ) const {
             return i >= size() ? 0 : (*this)[i];
       }
};

There are of course many wonderful things wrong with this approach – let us savour just a few of them:

  • It doesn’t work with existing code. The user probably has thousands of lines of code that declare std::string objects – if he wants to use the Peek() function with these, he will have to change much of his existing code base. This “refactoring” (how clever we were when we invented that term!) can only serve to waste time and introduce bugs.
  • It doesn’t allow the construction of MyString using anything but the default and the copy constructor. The std:;string class, on the other hand, has no less than six constructors that take parameters, all of which must be pointlessly re-implemented in MyString.
  • It may lead to undefined behaviour. Your patient may know about this one – none of the Standard Library template classes have virtual destructors. This means that any code that looks something like this:
    std::string * s = new MyString;
    ...
    delete s;
    

    will exhibit undefined behaviour. Now, as we positively want the humans to write code like this, you should whisper things like “Of course, you will never write code like that” and “MyString declares no new data members, so it will be all right” in your patient’s ear. Neither of these are true, of course, but humans love to be told what they want to hear, rather than the truth – look at the popularity of our fiendish programming Q&A websites for evidence of this.

It is useful to know what the the developer actually should do, if only so you can guide him away from it. Very simply, the C++ Standard Library classes should be extended using free functions. This means you write Peek() outside of any class:

char Peek( const std::string & s, unsigned int i ) {
   return i >= s.size() ? 0 : s[i];
}

which can be used like this:

std::string s = "abc";
char c = Peek( s, 100 );

Doing this has (unfortunately) none of the disadvantages of derivation, and would be the best (from their point of view) way to add functionality to any Standard Library class, not just std::string. However, you may be able to dissuade your patient from using it by suggesting that it is some way “inefficient”, something that the less experienced developer is always worrying about – I may have more to say about this in my next letter.

So dear Malware, may I wish you a Happy New Year, and a miserable and confused one to all programmers and developers.

Your affectionate uncle,

PUNCHTAPE
Under Consultant
Demonic Department of Obfuscation and Standardisation

Advertisements


4 Responses to “Letter the Fifth – Evils of Inheritance”

  1. 1 Nick Gorski

    “none of the Standard Library have virtual constructors”

    Should that be: “none of the Standard Library containers have virtual destructors”?

  2. 3 Nick Gorski

    That’s quite alright :] At least you’ve got your brain saying something. 😛 -GMan

  3. 4 Dave Shawley

    Very nice post Neil. I hadn’t even considered the constructor forwarding problems before this. I would go a step further with Peek and make std::string a template parameter. I think that people don’t understand that generic programming using templates is a different expression of OO. Oh, and you are a brave man linking to here from SO, but thanks for doing it. I’ll have to add your blog to my list of things to read when I don’t feel like working.


Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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 )

Google+ photo

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

Connecting to %s


%d bloggers like this: