Chris Gregory

Home Blog LinkedIn Github

Java to C++ - polymorphism

9/27/2015

As we saw earlier, the main goals of C++ are as follows:

Source: Bjarne Stroustrup, inventor of C++ "Make Simple Tasks Simple!" CppCon 2014

This means that when you have to make methods that accept general types, you have to make it fast and flexible. Java tries to do general types with interfaces and generic types. This works well, but incurs a big runtime overhead. Let's do it anyway, because you're going to see it somewhere eventually. This concept of making a interface then extending it is called polymorphism. Polymorphism is a very easy way to create abstractions but it is pretty slow. Here is how it works in C++. Next post I'll look at template metaprogramming which is like generic programming in Java on steroids.

class printable {
  public:
    virtual void print() = 0;
};

class one : public printable {
  public:
    void print() { std::cout << "one" << std::end; }
};

class two : public printable {
  public:
    void print() { std::cout << "two" << std::end; }
};

Here we see that we use a new keyword, virtual and some weird = 0 thing. virtual tells the compiler that this class should be extensible and overridden print methods should be called instead printable's own.

This is the default behavior in Java but it isn't in C++ for performance reasons. If a class isn't polymorphic, not having any virtual methods, then it can be turned into a plain old data structure and all calls to its "methods" are just function calls that take an implicit pointer to the struct. This means that using object orientation without inheritance is as fast as C!

The = 0 is the exact same as the abstract keyword. It just enforces that the printable "interface" must have an overridden print method to be able to be constructed.

One thing you should note is that you use a colon to show extension, rather than a keyword. The colon takes a list of classes and the way in which to extend them. By default, inheritance is private. This means that only your class knows that it is an instance of the other class. Most of the time private inheritance is used when you want to do advanced template metaprogramming and public inheritance is done most everywhere else. Protected inheritance is the other modifier, meaning that only subclasses have access to the data or to the knowledge of inheritance, as there are no packages in C++.

Now let's look at an example of subtle problems with polymorphism in C++. Java solves this by making everything a pointer, and the behavior of a pointer in C++ is the same intuitive thing that it is in Java. BTW putting braces in C++ enters a "sub scope". It's like an if(true) {}.

int main() {
    // Error!  Can't use a abstract class as value type!
    // printable x = sub();
    // Error!  Can't point a reference to an unnamed value!
    // printable& x = sub();

    one o;
    two t;
    {
        printable& x = o;
        x.print();
        // output one
    }
    {
        printable& x = t;
        x.print();
        // output two
    }
    {
        printable& x = t;
        x = o;
        x.print();
        // ouput two!  Remember that a reference is a pointer to one
        // unchangable memory location.  Assigning to it will corrupt
        // ``t`` rather than changing the memory location!
    }
    {
        printable* x = &t;
        x = &o;
        x->print();
        // output one!  Assigning to a pointer will change the pointer
        // rather than the memory!
    }
}

In the main method, we see that an interface / abstract class is best used as a pointer, which takes away the benefits of deterministic destruction at the end of scopes.

The problem with polymorphism is that it forces the entire class to be allocated differently and that method call to be looked up at runtime. Template Metaprogramming shifts this method lookup to compile time and makes your methods more general by removing interfaces and just accessing fields directly. This can even make your methods generically work over objects and native types (int, float...) all in the same way!