Templates vs. Virtual functions

You have probably heard about polymorphism before. Well, there are at least two different kinds of polymorphism in C++. Today, we’re going to talk about run time polymorphism via inheritance and compile time polymorphism via templates. Most people are familiar with polymorphism via inheritance. Typically we encounter it early in our programming career, often via some strange example about animals making various noises. Template polymorphism is not so well loved, but in this blog, we are going to give it a chance!

What is polymorphism anyway?

Polymorphism is type abstraction. We are doing polymorphism, when, we ignore some of the specifics of a given type, and treat it as different type, for example through an interface. The best way to understand it is via examples.

Polymorphism via inheritance

Let’s try our hand at a little subclass polymorphism. We are going to create a very simple base class with a virtual method. We will also create a subclass that inherits form this base class, and overrides our virtual base class method.

class SimpleBaseClass
{
public:
    virtual void DoSomethingFun() 
    {
        // put some fun stuff in here
    }
}

class SimpleSubClass : public SimpleBaseClass
{
public:
    void DoSomethingFun()
    {
        // put some different fun stuff here
    }
}

Now we can provide many different implementation of the DoSomethingFun method in different subclasses, and we can use them like so:

int main()
{
    SimpleBaseClass* polyObject = new SimpleSubClass();
    polyObject->DoSomethingFun();
    return 0;
}

When this all compiles, the compiler will create a special lookup table called a vtable. Then, because this is a virtual method, at run time, when the DoSomethingFun method is called on the polyObject pointer, the vtable will be used to find the implementation in the SimpleSubClass. That was polymorphism!

Polymorphism via templates

We have covered the bread and butter of polymorphism. However, we can achieve the same effect with templates! To do this, we are going to define a templated class, and two different implementation classes:

class FunImplementationClass
{
public:
    FunImplementation()
    {
        // put some fun stuff here
    }
}

class AnotherFunImplementationClass
{
public:
    FunImplementation()
    {
        // put some different fun stuff here
    }
}

template <typename T>
public TemplateBaseClass<T>
{
private:
    T implementation;
public:
    TemplateBaseClass(T implementation) : implementation(implementation)
    {
    }

    void DoSomethingFun()
    {
        implementation.FunImplementation();
    }
}

Now we have created a sort of base class like before. But, instead of defining different implementations in subclasses that inherit from this base class, we define them in classes that we pass in via template type parameters.

And we can use this in a very similar (and slightly more verbose) way to the traditional object oriented approach:

int main()
{
    TemplateBaseClass<FunImplementationClass> polyObject = TemplateBaseClass<FunImplementationClass>(FunImplementation());
    polyObject.DoSomethingFun()
    return 0;
}

This time, the compiler will use our templating to resolve which implementation to use, and it will do this at compile time, not run time.

Why would we even want to use templates like this?

There are some disadvantages to the template approach. The most obvious of which is that template programming is not as well known. If you use it, the other people who read, maintain and extend your code, are less likely to be familiar with this technique. So it will be a lot harder for them!

The other, is that templated code is a lot harder to debug. In particular, if you have ever had a compiler error from templated code, you will recognise the error message gore it produces.

I have also heard that templated code is liable to create very large binaries, as so much extra code is generated by the compiler. However I have never seen this being a problem in real life.

With all that said, why might you sill choose to use the templated version? The main reason is performance. There is a performance penalty associated with run time polymorphism. When the correct method is resolved at run time, it requires a look up in the vtable which adds a small but non-zero performance penalty.

In addition to this, when we use compile time polymorphism, the compiler knows exactly what code path we are going to follow. When we use run time polymorphism, that will only be resolved at run time. This means that the compiler has much greater flexibility to optimise our templated code. This can give us a significant performance boost!

Staying Safe in C++

What is Exception Safety?

Exceptions are gross. One of the problems with exceptions is that, as they break out of the normal control flow, they can potentially leave our program in a bad state. How do we avoid this?

Well, we can guarantee that we never throw an exception, either because our code is perfect, or, we catch and smoothly handle all exceptions at the point they are thrown. This is a worthy goal, but might not be entirely practical. So the alternative is to follow the philosophy of exception safety. This is the design philosophy that says that we can throw exceptions, but, when we do, we must leave things in a good state.

There are two different flavours of exception safety, strong exception safety and weak exception safety. Strong exception safety is a guarantee that when an exception is thrown during some operation, the overall state will be back to what it was before the operation started. In other words, our methods are atomic or transactional. Weak exception safety is the guarantee that when we throw an exception we will leave things in a valid state. In particular, both forms of exception safety guarantee that we will not leak any resources.

Usually we manage state via classes, and that is also how we think about exception safety. How we make a class exception safe depends on the state that our class manages, and the functionality it exposes via it’s methods.

An Example of Exception Safety

Here’s an example from a job interview I did recently. Suppose we have two strongly exception safe classes: ResourceManager1 and ResourceManager2. In our code we want to define another class, which we, optimistically, name, SafeCopyingClass, like so:

class SafeCopyingClass
{
private:
   int a;
   ResourceManager1 b;
   ResourceManager2* c;
}

The question is, how can we implement a copy constructor for this class in an exception safe way?

We have to copy three member variables. We know that copying an integer like the member a should not throw. This means that we should leave the copy of a until the very end, that way if something goes wrong with the other two copies, we won’t have to roll it back. So, to start, we are going to have something like this:

SafeCopyingClass(const SafeCopyingClass& other)
{
   /// lots of copying logic that might throw
   a = other.a;
}

Now what about copying the members b and c? Suppose we naively copy the objects b and c as below.

SafeCopyingClass(const& SafeCopyingClass& other)
{
   b = ResourceManager1(other.b);
   c = new ResourceManager2(*other.c);
   a = other.a;
}

If the copying of other.b throws, then we are still in the original state so we can just let the exception escape. However, if that first copy succeeds, and then the copy of the RescourceManager2 object throws, then we are not in the original pre-copy state. Indeed, things are even worse than that, we cannot safely get back to the original state. Anything we do to try and restore the pre-copy state, would involve copying ResourceManager1 objects, which would potentially throw again.

So, instead, we are going to copy the ResourceManager2 object first. We are in luck here, because c is in fact a pointer, which is a primitive type, and, although copying the object it points to could throw, copying the pointer itself should not. This means that, we can split the operation into a copy that may throw but leaves our state unchanged, and an assignment that changes our state but should not throw. Concretely, we first copy the other.c object and store the result in a temporary pointer, and then separately assign value in that temporary point to c.

We do this copy of the underlying ResourceManager2 object first, if this throws, as we have not altered the state of the SafeCopyingClass object, we can let this exception escape. The assignment of the value in other.c to c, alters the state so it should go at the end, after all the code that may throw. So our copy constructor now looks like this:

SafeCopyingClass(const SafeCopyingClass& other)
{
   ResourceManager2* temp_c = new ResourceManager2(*other.c);
   // more copying logic that might throw
   c = temp_c;
   a = other.a;
}

Now we just have to deal with the copying of our ResourceManager1 object b. After creating the temporary pointer for our other.c but before we assign that pointer to c, we are still in the original state, so we can copy b and allow exceptions to escape, at this point, like so:

SafeCopyingClass(const SafeCopyingClass& other)
{
   ResourceManager2* temp_c = new ResourceManager2(*other.c);
   b = ResourceManager1(other.b);
   c = temp_c;
   a = other.a;
}

However, there is still one issue with our code. We have a potential resource leak, and that is not only bad practice, it is not exception safe. Suppose, when we copy the other.b object an exception is thrown. Then control will leave this copy constructor. However we created an object of type ResourceManager2. The pointer temp_c is lost, but the object will live on, so we are leaking resources.

So, if the copy of other.b throws, we need to delete the object pointed to by temp_c. To do this, we wrap the ResourceManager1 copy in a try catch block. Then if an exception is thrown we can clean things up and rethrow the exception. So, here his our finished copy constructor:

SafeCopyingClass(const& SafeCopyingClass other)
{
   ResourceManager2* temp_c = new ResourceManager2(other.c);
   try
   {
      b = ResourceManager1(other.b);
   } 
   catch(...)
   {
      delete temp_c;
      throw; 
   }
   c = temp_c;
   a = other.a;
}

What is the general strategy here? We split our copying into stuff that may throw and stuff that should not throw. We do everything that might throw before everything that will not throw. That makes any potential rollback a lot simpler. When we have a pointers, we should copy the underlying objects first and store the result in temporary pointers. After that, we do the rest of the potentially throwing copies, this is where we have to be aware of potential resource leaks and non trivial rollbacks.

Constructors and Destructors in C++ – Part 3

We’ve talked a lot about how construction and destruction work. Now, finally, it’s time to see how they go wrong. Firstly, let’s say that an object is being constructed and an exception is thrown. In this situation the classes destructor is not called. This, in general, should not be a problem. The only exception throwing code you should have in a constructor is code that manages some resource. And, you should manage at most one resource per class. So if an exception is thrown in your constructor, it means that the resource you are managing has not been setup and so the destructor does not need to be called.

So if we have a class like this:

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
		throw std::exception();
	}

	virtual ~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

and we run the following main function,

int main()
{
    try
    {
        Base baseObject;
    }
    catch(std::exception& e)
    {
        std::cout << "Exception caught" << std::endl;
    }
    return 0;
}

we will see:

Base Constructor
Exception caught

As you see, no calls to the destructor. Now suppose, with the same main function, we throw an exception from a derived class like so,

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
	}

	virtual ~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

class Derived : public Base
{
public:
	Derived() : Base()
	{
		std::cout << "Derived Constructor" << std::endl;
		throw std::exception();
	}

	Derived(int i)
	{
		std::cout << "Derived with parameter Constructor" << std::endl;
	}

	virtual ~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

Then we will see:

Base Constructor
Derived Constructor
Base Destructor
Exception caught

The Derived destructor is not called, but the Base Destructor is. This is because by the time the exception is thrown in the Derived class, we have completely the construction of the Base class, so that will need to be destroyed as normal.

Local objects that are constructed within the constructor will be destroyed as normal when an exception is thrown. So, for example code like this:

class Simple
{
public:
	Simple()
	{
		std::cout << "Simple Constructor" << std::endl;
	}

	virtual ~Simple()
	{
		std::cout << "Simple Destructor" << std::endl;
	}
};

class Basic
{
public:
	Basic()
	{
		std::cout << "Basic Constructor" << std::endl;
                Simple simpleObject;
		throw std::exception();
	}

	virtual ~Basic()
	{
		std::cout << "Basic Destructor" << std::endl;
	}
};

when executed via,

int main()
{
	try
	{
		Basic basicObject;
	}
	catch(std::exception& e)
	{
		std::cout << "Exception caught" << std::endl;
	}
	return 0;
}

will produce:

Basic Constructor
Simple Constructor
Simple Destructor
Exception caught

So, as we have seen, you can throw exceptions from the constructor. You cannot however throw an exception from a destructor. Try building the following code,

class Simple
{
public:
	Simple()
	{
		std::cout << "Simple Constructor" << std::endl;
	}

	virtual ~Simple()
	{
		std::cout << "Simple Destructor" << std::endl;
                throw std::exception();
	}
};

You should get a warn telling you that destructors are “noexcept” in C++. If you run this code as before, you will get:

Simple Constructor
Simple Destructor
terminate called after throwing an instance of 'std::exception'
  what():  std::exception
Aborted (core dumped)

C++ will always terminate when an exception like this is thrown in a destructor. The reason is simple. Suppose we throw an exception and then start unwinding the stack. If, when we destroy an object on the stack it’s destructor threw another exception, there is no way to catch both exceptions. We cannot catch one exception and abandon the other, so the program gives up and terminates whenever an exception is thrown in a destructor.

Constructors and Destructors in C++ – Part 2

In our previous post we discussed constructors and destructors for local objects. Now, suppose we have the same hierarchy of classes, Base, Derived and DerivedAgain, and we constructed a DerivedAgain object the heap, like so:

int main()
{
    DerivedAgain* derivedAgainObject = new DerivedAgainObject();
    return 0;
}

When we run this we will see the following,

Base Constructor
Derived Constructor
DerivedAgain Constructor

The constructors were called in the same order as before. However, because our DerivedAgain object was created on the heap the destructor was never called. If we want to destroy our object we must explicitly use delete.

int main()
{
    DerivedAgain* derivedAgainObject = new DerivedAgainObject();
    delete derivedAgainObject;
    return 0;
}

The above will output the following to the command line,

Base Constructor
Derived Constructor 
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

Let’s consider what happens when we have a pointer of type Derived that points to an object of typed DerivedAgain. Say we run:

Derived* derivedPointer = new DerivedAgain();
delete derivedPointer;
return 0;

When we run this code we will see:

Base Constructor
Derived Constructor
DerivedAgain Constructor
Derived Destructor
Base Destructor

The constructors are the same, because we are creating a DerivedAgain object as before. However, now we are calling delete on a pointer of type Derived. So only the Derived and Base class destructors are called.

We can avoid this problem by making our destructors virtual.

class Base
{
public:
        Base()
        {
                std::cout << "Base Constructor" << std::endl;
        }

        virtual ~Base()
        {
                std::cout << "Base Destructor" << std::endl;
        }
};

class Derived : public Base
{
public:
        Derived() : Base()
        {
                std::cout << "Derived Constructor" << std::endl;
        }

        virtual ~Derived()
        {
                std::cout << "Derived Destructor" << std::endl;
        }
};

class DerivedAgain : public Derived
{
public:
        DerivedAgain() : Derived()
        {
                std::cout << "DerivedAgain Constructor" << std::endl;
        }

        ~DerivedAgain()
        {
                std::cout << "DerivedAgain Destructor" << std::endl;
        }
};

Now when we run,

int main()
{
        Derived* derivedPointer = new DerivedAgain();
        delete derivedPointer;
        return 0;
}

we will see:

Base Constructor
Derived Constructor
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

Even though we have a pointer of type Derived, because the destructor is virtual, when we call delete, the DerivedAgain destructor gets called. What’s interesting here, is that we always call all the destructors upwards through the type hierarchy, the use of virtual ensures that we start at the right level. For this reason, we should usually make our destructors virtual.

We can even make our destructors pure virtual. However, we will have to give this pure virtual destructor a body. It is a common misconception that a pure virtual function necessarily can’t have a body, this is not true. However pure virtual destructors are probably one of the only examples of when you would want to do it. The only reason we would want to make a destructor pure virtual is that we want to make a class abstract and the destructor is the only method. In my opinion this is a very unlikely to happen, so it’s not something we should really worry about.

In the next post we will have a look at what happens when things go wrong in construction and destruction.

Constructors and Destructors in C++ – Part 1

We’re going to think a little bit about constructing and destroying objects in C++. Let’s say we have three very simple classes, Base, Derived and DerivedAgain.

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
	}

	~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

class Derived : public Base
{
public:
	Derived()
	{
		std::cout << "Derived Constructor" << std::endl;
	}

	~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

class DerivedAgain : public Derived
{
public:
	DerivedAgain()
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Now suppose we run the following code,

int main()
{
	DerivedAgain derivedAgainObject;
	return 0;
}

The output will be:

Base Constructor
Derived Constructor 
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

Why is this? Well, to construct the DerivedAgain object, first we must construct aDerived object and to construct a Derived object, first we must construct a Base object. Similarly, when the object goes out of scope, to destroy it, first the DerivedAgain destructor is called, then the Derived destructor and then the Base Destructor. So, when creating an object we step down through the inheritance hierarchy, and when destroying it we step back up through the hierarchy.

We can call these constructors explicitly. Indeed the above code is exactly quivalent to:

class Base
{
public:
	Base()
	{
		std::cout << "Base Constructor" << std::endl;
	}

	~Base()
	{
		std::cout << "Base Destructor" << std::endl;
	}
};

class Derived : public Base
{
public:
	Derived() : Base()
	{
		std::cout << "Derived Constructor" << std::endl;
	}

	~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

class DerivedAgain : public Derived
{
public:
	DerivedAgain() : Derived()
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Let’s change things up a little bit, suppose we have the following situation.

class Derived : public Base
{
public:
	Derived()
	{
		std::cout << "Derived Constructor" << std::endl;
	}

	Derived(int i)
	{
		std::cout << "Derived Constructor With Parameter" << std::endl;
	}

	~Derived()
	{
		std::cout << "Derived Destructor" << std::endl;
	}
};

class DerivedAgain : public Derived
{
public:
	DerivedAgain() : Derived(5)
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Now we are explicitly calling a non-default constructor from the Derived class. All the other implicit calls to default constructors remain the same. When we run the main function as before, we will see:

Base Constructor
Derived Constructor with parameter Constructor
DerivedAgain Constructor
DerivedAgain Destructor
Derived Destructor
Base Destructor

You cannot however do something like this:

class DerivedAgain : public Derived
{
public:
	DerivedAgain() : Base()
	{
		std::cout << "DerivedAgain Constructor" << std::endl;
	}

	~DerivedAgain()
	{
		std::cout << "DerivedAgain Destructor" << std::endl;
	}
};

Here, we are trying to call the Base constructor from the DerivedAgain class. This will not compile, we can only call constructors from the classes that we directly inherit from.

So far we have only looked at constructors and destructors for local objects, that is, without using the new keyword. In part 2, we will look at what happens when we construct and destroy objects dynamically.