override and final in C++

override and final are two new qualifiers introduced in C++11. The use of these qualifiers is optional. They are meant to be used with virtual methods to show the intention of the method. The compiler uses these qualifiers to check if your intention matches the actual ground truth in your code and throws a compile error if it does not. Thus, it helps to catch bugs earlier at compile time.

  • When you specify override for a method, you are indicating to the compiler that this is a virtual method and it is overriding a virtual method with the same signature in one of the base classes that the current class inherits from. If the method is not inheriting from any virtual method with the same signature, the compiler throws an error. Thus if you made a mistake in the function signature while defining this method, you would not have caught it unless you used this qualifier.

  • When you specify final for a method, you are indicating that this is a virtual method and that no class that inherits from the current class can override this method. If any method tries to override this method in an inherited class, the compiler throws an error.

  • If override or final are used with non-virtual methods, the compiler throws an error.

  • These qualifiers are specified after the function input arguments and should be specified after const if the virtual method is a const method. If you put these qualifiers before a const, you will get a weird error with GCC that gives no hint that this is because of the order of qualifiers is wrong!

  • These qualifiers are to be specified only with the method declaration. If you try to use them with the method definition, the compiler will throw an error.

  • You can specify override final for a method, but it is the same as using final.

  • override is not allowed to be used with the base virtual method. This is for the obvious reason that the base virtual method is the first virtual method and it is not overriding any other method.

  • final can be used with the base virtual method. This can be used to specify that the first base virtual method cannot be overridden in any inherited class.

This code example shows how to use these qualifiers:

Notes of talk: C++ in the 21st century

I recently came across a 2014 talk by Arvid Norberg about the new features in C++11. The video is here and slides are here.

C++ is huge and getting bigger every day. So, I keep discovering interesting new features that I like to note down for use in my own code. Below are my notes from this talk. I do not note aspects that I already know well. This talk has examples that are small but illustrative, so if you hit any of these features, you should see the video to look at the examples.

For loops

  • std::begin and std::end work on C arrays too. Note that this is only when the array size is known. So, the array must have been created in the same local scope.

decltype

  • decltype deduces the type of an expression. So its use is in type expressions. For example, as template arguments.
// vector of the return type of function f
std::vector<decltype(f())> vals;
  • Internally, it is used by auto to deduce type of expression

lambda functions

  • Lambda expression yields an unnamed function object. The tiny examples in the talk are good.

override

  • This is to help programmers find errors. For example, when virtual method in base class is not const and in derived it is. Programmer might miss this error. If virtual method in derived class is declared override and it is actually not, compiler will complain.

unique_ptr

  • This smart pointer is not copyable, but movable. It is deleted when pointer goes out of scope.
  • Many functions create a heap-allocated object and return it. Traditionally, programmers had to worry about the ownership and lifetime of such a returned object. Return it as unique_ptr and forget about these worries.
  • Also great for storing such heap-allocated objects in containers.

error_code

This C++11 feature was something new to me! I did not understand how to apply it either. I might need to study this in future.

  • error_code represents an error. It has error_value integral value indicating what is the error. It has category indicating domain of error value.
  • category is an abstract base class implementing conversion of error_value to human readable message.

chrono

  • There are a whole bunch of old C, C++, Unix and POSIX time functions. They are not platform agnostic, have low time resolutions, have no type safety (milliseconds value can be passed to a function that takes in microseconds and so on) and are not monotonic. Monotonic in this context means that if you measure a time before DST is turned on and after it, the latter value should always be larger, though the wall clock may have been turned back by DST.
  • Chrono introduces a clock with its own epoch (start of life) and its own resolution.
  • time_point: A point in time relative to epoch. It has its resolution encoded inside it.
  • time_duration: Difference of two time points. It has its resolution encoded inside it.
  • Because these types have their resolutions embedded inside, two durations of different resolutions can be added together to produce a duration that has resolution that is highest or higher than both. They can be passed to function that accepts in a different resolution. The template machinery ensures that it all converts correctly.